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