2.5 - A few bugfixes...
[blender.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_arithb.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 (expecting it to be an NLA track) */
118         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE);
119         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
120         
121         for (ale= anim_data.first; ale; ale= ale->next) {
122                 // TODO: need some way to select active animdata too...
123                 if (ale->type == ANIMTYPE_NLATRACK) {
124                         NlaTrack *nlt= (NlaTrack *)ale->data;
125                         AnimData *adt= ale->adt;
126                         
127                         /* found it, now set the pointers */
128                         if (adt_ptr) {
129                                 /* AnimData pointer */
130                                 RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
131                         }
132                         if (nlt_ptr) {
133                                 /* NLA-Track pointer */
134                                 RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
135                         }
136                         if (strip_ptr) {
137                                 /* NLA-Strip pointer */
138                                 NlaStrip *strip= BKE_nlastrip_find_active(nlt);
139                                 RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
140                         }
141                         
142                         found= 1;
143                         break;
144                 }
145         }
146         
147         /* free temp data */
148         BLI_freelistN(&anim_data);
149         
150         return found;
151 }
152
153 #if 0
154 static int nla_panel_poll(const bContext *C, PanelType *pt)
155 {
156         return nla_panel_context(C, NULL, NULL);
157 }
158 #endif
159
160 static int nla_animdata_panel_poll(const bContext *C, PanelType *pt)
161 {
162         PointerRNA ptr;
163         return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL));
164 }
165
166 static int nla_track_panel_poll(const bContext *C, PanelType *pt)
167 {
168         PointerRNA ptr;
169         return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL));
170 }
171
172 static int nla_strip_panel_poll(const bContext *C, PanelType *pt)
173 {
174         PointerRNA ptr;
175         return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL));
176 }
177
178 static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt)
179 {
180         PointerRNA ptr;
181         NlaStrip *strip;
182         
183         if (!nla_panel_context(C, NULL, NULL, &ptr))
184                 return 0;
185         if (ptr.data == NULL)
186                 return 0;
187         
188         strip= ptr.data;
189         return (strip->type == NLASTRIP_TYPE_CLIP);
190 }
191
192 /* -------------- */
193
194 /* active AnimData */
195 static void nla_panel_animdata (const bContext *C, Panel *pa)
196 {
197         PointerRNA adt_ptr;
198         AnimData *adt;
199         uiLayout *layout= pa->layout;
200         uiLayout *row;
201         uiBlock *block;
202         
203         /* check context and also validity of pointer */
204         if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
205                 return;
206         adt= adt_ptr.data;
207         
208         block= uiLayoutGetBlock(layout);
209         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
210         
211         /* Active Action Properties ------------------------------------- */
212         /* action */
213         row= uiLayoutRow(layout, 1);
214                 uiTemplateID(row, C, &adt_ptr, "action", NULL, NULL/*"ACT_OT_new", "ACT_OT_unlink"*/); // XXX: need to make these operators
215         
216         /* extrapolation */
217         row= uiLayoutRow(layout, 1);
218                 uiItemR(row, NULL, 0, &adt_ptr, "action_extrapolation", 0);
219         
220         /* blending */
221         row= uiLayoutRow(layout, 1);
222                 uiItemR(row, NULL, 0, &adt_ptr, "action_blending", 0);  
223                 
224         /* influence */
225         row= uiLayoutRow(layout, 1);
226                 uiItemR(row, NULL, 0, &adt_ptr, "action_influence", 0);
227 }
228
229 /* active NLA-Track */
230 static void nla_panel_track (const bContext *C, Panel *pa)
231 {
232         PointerRNA nlt_ptr;
233         uiLayout *layout= pa->layout;
234         uiLayout *row;
235         uiBlock *block;
236         
237         /* check context and also validity of pointer */
238         if (!nla_panel_context(C, NULL, &nlt_ptr, NULL))
239                 return;
240         
241         block= uiLayoutGetBlock(layout);
242         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
243         
244         /* Info - Active NLA-Context:Track ----------------------  */
245         row= uiLayoutRow(layout, 1);
246                 uiItemR(row, NULL, ICON_NLA, &nlt_ptr, "name", 0);
247 }
248
249 /* generic settings for active NLA-Strip */
250 static void nla_panel_properties(const bContext *C, Panel *pa)
251 {
252         PointerRNA strip_ptr;
253         uiLayout *layout= pa->layout;
254         uiLayout *column, *row, *subcol;
255         uiBlock *block;
256         
257         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
258                 return;
259         
260         block= uiLayoutGetBlock(layout);
261         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
262         
263         /* Strip Properties ------------------------------------- */
264         /* strip type */
265         row= uiLayoutColumn(layout, 1);
266                 uiItemR(row, NULL, ICON_NLA, &strip_ptr, "name", 0); // XXX icon?
267                 uiItemR(row, NULL, 0, &strip_ptr, "type", 0);
268         
269         /* strip extents */
270         column= uiLayoutColumn(layout, 1);
271                 uiItemL(column, "Strip Extents:", 0);
272                 uiItemR(column, NULL, 0, &strip_ptr, "start_frame", 0);
273                 uiItemR(column, NULL, 0, &strip_ptr, "end_frame", 0);
274         
275         /* extrapolation */
276         row= uiLayoutRow(layout, 1);
277                 uiItemR(row, NULL, 0, &strip_ptr, "extrapolation", 0);
278         
279         /* blending */
280         row= uiLayoutRow(layout, 1);
281                 uiItemR(row, NULL, 0, &strip_ptr, "blending", 0);
282                 
283         /* blend in/out + autoblending
284          *      - blend in/out can only be set when autoblending is off
285          */
286         column= uiLayoutColumn(layout, 1);
287                 uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_influence")==0); 
288                 uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0); // XXX as toggle?
289                 
290                 subcol= uiLayoutColumn(column, 1);
291                         uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0); 
292                         uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0);
293                         uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0);
294                 
295         /* settings */
296         column= uiLayoutColumn(layout, 1);
297                 uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "animated_influence") || RNA_boolean_get(&strip_ptr, "animated_time"))); 
298                 uiItemL(column, "Playback Settings:", 0);
299                 uiItemR(column, NULL, 0, &strip_ptr, "muted", 0);
300                 uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0);
301 }
302
303
304 /* action-clip only settings for active NLA-Strip */
305 static void nla_panel_actclip(const bContext *C, Panel *pa)
306 {
307         PointerRNA strip_ptr;
308         uiLayout *layout= pa->layout;
309         uiLayout *column, *row;
310         uiBlock *block;
311
312         /* check context and also validity of pointer */
313         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
314                 return;
315         
316         block= uiLayoutGetBlock(layout);
317         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
318                 
319         /* Strip Properties ------------------------------------- */
320         /* action pointer */
321         row= uiLayoutRow(layout, 1);
322                 uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0);
323                 
324         /* action extents */
325         // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
326         column= uiLayoutColumn(layout, 1);
327                 uiItemL(column, "Action Extents:", 0);
328                 uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0);
329                 uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0);
330                 
331         /* action usage */
332         column= uiLayoutColumn(layout, 1);
333                 uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_time")==0); 
334                 uiItemL(column, "Playback Settings:", 0);
335                 uiItemR(column, NULL, 0, &strip_ptr, "scale", 0);
336                 uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0);
337 }
338
339 /* evaluation settings for active NLA-Strip */
340 static void nla_panel_evaluation(const bContext *C, Panel *pa)
341 {
342         PointerRNA strip_ptr;
343         uiLayout *layout= pa->layout;
344         uiLayout *column, *subcolumn;
345         uiBlock *block;
346
347         /* check context and also validity of pointer */
348         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
349                 return;
350                 
351         block= uiLayoutGetBlock(layout);
352         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
353                 
354         column= uiLayoutColumn(layout, 1);
355                 uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0);
356                 
357                 subcolumn= uiLayoutColumn(column, 1);
358                 uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_influence"));       
359                         uiItemR(subcolumn, NULL, 0, &strip_ptr, "influence", 0);
360                 
361         
362         column= uiLayoutColumn(layout, 1);
363                 uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0);
364                 
365                 subcolumn= uiLayoutColumn(column, 1);
366                 uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_time"));
367                         uiItemR(subcolumn, NULL, 0, &strip_ptr, "strip_time", 0);
368 }
369
370 /* F-Modifiers for active NLA-Strip */
371 static void nla_panel_modifiers(const bContext *C, Panel *pa)
372 {
373         PointerRNA strip_ptr;
374         NlaStrip *strip;
375         FModifier *fcm;
376         uiLayout *col, *row;
377         uiBlock *block;
378
379         /* check context and also validity of pointer */
380         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
381                 return;
382         strip= strip_ptr.data;
383                 
384         block= uiLayoutGetBlock(pa->layout);
385         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
386         
387         /* 'add modifier' button at top of panel */
388         {
389                 row= uiLayoutRow(pa->layout, 0);
390                 block= uiLayoutGetBlock(row);
391                 
392                 // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
393                 // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
394                 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");
395         }
396         
397         /* draw each modifier */
398         for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) {
399                 col= uiLayoutColumn(pa->layout, 1);
400                 
401                 ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
402         }
403 }
404
405 /* ******************* general ******************************** */
406
407
408 void nla_buttons_register(ARegionType *art)
409 {
410         PanelType *pt;
411         
412         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
413         strcpy(pt->idname, "NLA_PT_animdata");
414         strcpy(pt->label, "Animation Data");
415         pt->draw= nla_panel_animdata;
416         pt->poll= nla_animdata_panel_poll;
417         pt->flag= PNL_DEFAULT_CLOSED;
418         BLI_addtail(&art->paneltypes, pt);
419         
420         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
421         strcpy(pt->idname, "NLA_PT_track");
422         strcpy(pt->label, "Active Track");
423         pt->draw= nla_panel_track;
424         pt->poll= nla_track_panel_poll;
425         BLI_addtail(&art->paneltypes, pt);
426         
427         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
428         strcpy(pt->idname, "NLA_PT_properties");
429         strcpy(pt->label, "Active Strip");
430         pt->draw= nla_panel_properties;
431         pt->poll= nla_strip_panel_poll;
432         BLI_addtail(&art->paneltypes, pt);
433         
434         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
435         strcpy(pt->idname, "NLA_PT_actionclip");
436         strcpy(pt->label, "Action Clip");
437         pt->draw= nla_panel_actclip;
438         pt->poll= nla_strip_actclip_panel_poll;
439         BLI_addtail(&art->paneltypes, pt);
440         
441         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
442         strcpy(pt->idname, "NLA_PT_evaluation");
443         strcpy(pt->label, "Evaluation");
444         pt->draw= nla_panel_evaluation;
445         pt->poll= nla_strip_panel_poll;
446         BLI_addtail(&art->paneltypes, pt);
447         
448         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
449         strcpy(pt->idname, "NLA_PT_modifiers");
450         strcpy(pt->label, "Modifiers");
451         pt->draw= nla_panel_modifiers;
452         pt->poll= nla_strip_panel_poll;
453         BLI_addtail(&art->paneltypes, pt);
454 }
455
456 static int nla_properties(bContext *C, wmOperator *op)
457 {
458         ScrArea *sa= CTX_wm_area(C);
459         ARegion *ar= nla_has_buttons_region(sa);
460         
461         if(ar) {
462                 ar->flag ^= RGN_FLAG_HIDDEN;
463                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
464                 
465                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
466                 ED_area_tag_redraw(sa);
467         }
468         return OPERATOR_FINISHED;
469 }
470
471 void NLA_OT_properties(wmOperatorType *ot)
472 {
473         ot->name= "Properties";
474         ot->idname= "NLA_OT_properties";
475         
476         ot->exec= nla_properties;
477         ot->poll= ED_operator_nla_active;
478         
479         /* flags */
480         ot->flag= 0;
481 }