Merge with -r 22620:23107.
[blender.git] / source / blender / editors / space_action / action_draw.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) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /* System includes ----------------------------------------------------- */
31
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <float.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45
46 /* Types --------------------------------------------------------------- */
47
48 #include "DNA_listBase.h"
49 #include "DNA_anim_types.h"
50 #include "DNA_action_types.h"
51 #include "DNA_armature_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_particle_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_constraint_types.h"
60 #include "DNA_key_types.h"
61 #include "DNA_lamp_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_meta_types.h"
64 #include "DNA_userdef_types.h"
65 #include "DNA_gpencil_types.h"
66 #include "DNA_windowmanager_types.h"
67 #include "DNA_world_types.h"
68
69 #include "BKE_action.h"
70 #include "BKE_depsgraph.h"
71 #include "BKE_fcurve.h"
72 #include "BKE_key.h"
73 #include "BKE_material.h"
74 #include "BKE_object.h"
75 #include "BKE_global.h"         // XXX remove me!
76 #include "BKE_context.h"
77 #include "BKE_utildefines.h"
78
79 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
80
81 #include "BIF_gl.h"
82 #include "BIF_glutil.h"
83
84 #include "UI_interface.h"
85 #include "UI_interface_icons.h"
86 #include "UI_resources.h"
87 #include "UI_view2d.h"
88
89 #include "ED_anim_api.h"
90 #include "ED_keyframing.h"
91 #include "ED_keyframes_draw.h"
92 #include "ED_screen.h"
93 #include "ED_space_api.h"
94
95
96 /* ************************************************************************* */
97 /* Channel List */
98
99 /* left hand part */
100 void draw_channel_names(bContext *C, bAnimContext *ac, SpaceAction *saction, ARegion *ar) 
101 {
102         ListBase anim_data = {NULL, NULL};
103         bAnimListElem *ale;
104         int filter;
105         
106         View2D *v2d= &ar->v2d;
107         float y= 0.0f;
108         int items, height;
109         
110         /* build list of channels to draw */
111         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
112         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
113         
114         /* Update max-extent of channels here (taking into account scrollers):
115          *      - this is done to allow the channel list to be scrollable, but must be done here
116          *        to avoid regenerating the list again and/or also because channels list is drawn first
117          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
118          *        start of list offset, and the second is as a correction for the scrollers.
119          */
120         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
121         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
122                 /* don't use totrect set, as the width stays the same 
123                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
124                  */
125                 v2d->tot.ymin= (float)(-height);
126         }
127         /* need to do a view-sync here, so that the keys area doesn't jump around */
128         UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL);
129         
130         /* loop through channels, and set up drawing depending on their type  */        
131         {       /* first pass: just the standard GL-drawing for backdrop + text */
132                 y= (float)ACHANNEL_FIRST;
133                 
134                 for (ale= anim_data.first; ale; ale= ale->next) {
135                         float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
136                         float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
137                         
138                         /* check if visible */
139                         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
140                                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
141                         {
142                                 /* draw all channels using standard channel-drawing API */
143                                 ANIM_channel_draw(ac, ale, yminc, ymaxc);
144                         }
145                         
146                         /* adjust y-position for next one */
147                         y -= ACHANNEL_STEP;
148                 }
149         }
150         {       /* second pass: widgets */
151                 uiBlock *block= uiBeginBlock(C, ar, "dopesheet channel buttons", UI_EMBOSS);
152                 
153                 y= (float)ACHANNEL_FIRST;
154                 
155                 for (ale= anim_data.first; ale; ale= ale->next) {
156                         float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
157                         float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
158                         
159                         /* check if visible */
160                         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
161                                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
162                         {
163                                 /* draw all channels using standard channel-drawing API */
164                                 ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
165                         }
166                         
167                         /* adjust y-position for next one */
168                         y -= ACHANNEL_STEP;
169                 }
170                 
171                 uiEndBlock(C, block);
172                 uiDrawBlock(C, block);
173         }
174         
175         /* free tempolary channels */
176         BLI_freelistN(&anim_data);
177 }
178
179 /* ************************************************************************* */
180 /* Keyframes */
181
182 /* extra padding for lengths (to go under scrollers) */
183 #define EXTRA_SCROLL_PAD        100.0f
184
185 /* draw keyframes in each channel */
186 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
187 {
188         ListBase anim_data = {NULL, NULL};
189         bAnimListElem *ale;
190         int filter;
191         
192         View2D *v2d= &ar->v2d;
193         bDopeSheet *ads= &saction->ads;
194         AnimData *adt= NULL;
195         
196         float act_start, act_end, y;
197         int height, items;
198         
199         char col1[3], col2[3];
200         char col1a[3], col2a[3];
201         char col1b[3], col2b[3];
202         
203         
204         /* get theme colors */
205         UI_GetThemeColor3ubv(TH_BACK, col2);
206         UI_GetThemeColor3ubv(TH_HILITE, col1);
207         
208         UI_GetThemeColor3ubv(TH_GROUP, col2a);
209         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
210         
211         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
212         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
213         
214         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
215
216         /* if in NLA there's a strip active, map the view */
217         if (ac->datatype == ANIMCONT_ACTION) {
218                 adt= ANIM_nla_mapping_get(ac, NULL);
219                 
220                 /* start and end of action itself */
221                 calc_action_range(ac->data, &act_start, &act_end, 0);
222         }
223         
224         /* build list of channels to draw */
225         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
226         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
227         
228         /* Update max-extent of channels here (taking into account scrollers):
229          *      - this is done to allow the channel list to be scrollable, but must be done here
230          *        to avoid regenerating the list again and/or also because channels list is drawn first
231          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
232          *        start of list offset, and the second is as a correction for the scrollers.
233          */
234         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
235         /* don't use totrect set, as the width stays the same 
236          * (NOTE: this is ok here, the configuration is pretty straightforward) 
237          */
238         v2d->tot.ymin= (float)(-height);
239         
240         /* first backdrop strips */
241         y= (float)(-ACHANNEL_HEIGHT);
242         glEnable(GL_BLEND);
243         
244         for (ale= anim_data.first; ale; ale= ale->next) {
245                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
246                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
247                 
248                 /* check if visible */
249                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
250                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
251                 {
252                         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
253                         int sel=0;
254                         
255                         /* determine if any need to draw channel */
256                         if (ale->datatype != ALE_NONE) {
257                                 /* determine if channel is selected */
258                                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
259                                         sel= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
260                                 
261                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
262                                         switch (ale->type) {
263                                                 case ANIMTYPE_SCENE:
264                                                 case ANIMTYPE_OBJECT:
265                                                 {
266                                                         if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
267                                                         else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
268                                                 }
269                                                         break;
270                                                 
271                                                 case ANIMTYPE_FILLACTD:
272                                                 case ANIMTYPE_FILLMATD:
273                                                 case ANIMTYPE_FILLPARTD:
274                                                 case ANIMTYPE_DSSKEY:
275                                                 case ANIMTYPE_DSWOR:
276                                                 {
277                                                         if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
278                                                         else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
279                                                 }
280                                                         break;
281                                                 
282                                                 case ANIMTYPE_GROUP:
283                                                 {
284                                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
285                                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
286                                                 }
287                                                         break;
288                                                 
289                                                 default:
290                                                 {
291                                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
292                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
293                                                 }
294                                                         break;
295                                         }
296                                         
297                                         /* draw region twice: firstly backdrop, then the current range */
298                                         glRectf(v2d->cur.xmin,  (float)y-ACHANNEL_HEIGHT_HALF,  v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
299                                         
300                                         if (ac->datatype == ANIMCONT_ACTION)
301                                                 glRectf(act_start,  (float)y-ACHANNEL_HEIGHT_HALF,  act_end,  (float)y+ACHANNEL_HEIGHT_HALF);
302                                 }
303                                 else if (ac->datatype == ANIMCONT_SHAPEKEY) {
304                                         /* all frames that have a frame number less than one
305                                          * get a desaturated orange background
306                                          */
307                                         glColor4ub(col2[0], col2[1], col2[2], 0x22);
308                                         glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, 1.0f, (float)y+ACHANNEL_HEIGHT_HALF);
309                                         
310                                         /* frames one and higher get a saturated orange background */
311                                         glColor4ub(col2[0], col2[1], col2[2], 0x44);
312                                         glRectf(1.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
313                                 }
314                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
315                                         /* frames less than one get less saturated background */
316                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
317                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
318                                         glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF);
319                                         
320                                         /* frames one and higher get a saturated background */
321                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
322                                         else glColor4ub(col2[0], col2[1], col2[2], 0x44);
323                                         glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
324                                 }
325                         }
326                 }
327                 
328                 /*      Increment the step */
329                 y -= ACHANNEL_STEP;
330         }               
331         glDisable(GL_BLEND);
332         
333         /* Draw keyframes 
334          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
335          *         This is to try to optimise this for heavier data sets
336          *      2) Keyframes which are out of view horizontally are disregarded 
337          */
338         y= (float)(-ACHANNEL_HEIGHT);
339         
340         for (ale= anim_data.first; ale; ale= ale->next) {
341                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
342                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
343                 
344                 /* check if visible */
345                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
346                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
347                 {
348                         /* check if anything to show for this channel */
349                         if (ale->datatype != ALE_NONE) {
350                                 adt= ANIM_nla_mapping_get(ac, ale);
351                                 
352                                 /* draw 'keyframes' for each specific datatype */
353                                 switch (ale->datatype) {
354                                         case ALE_SCE:
355                                                 draw_scene_channel(v2d, ads, ale->key_data, y);
356                                                 break;
357                                         case ALE_OB:
358                                                 draw_object_channel(v2d, ads, ale->key_data, y);
359                                                 break;
360                                         case ALE_ACT:
361                                                 draw_action_channel(v2d, adt, ale->key_data, y);
362                                                 break;
363                                         case ALE_GROUP:
364                                                 draw_agroup_channel(v2d, adt, ale->data, y);
365                                                 break;
366                                         case ALE_FCURVE:
367                                                 draw_fcurve_channel(v2d, adt, ale->key_data, y);
368                                                 break;
369                                         case ALE_GPFRAME:
370                                                 draw_gpl_channel(v2d, ads, ale->data, y);
371                                                 break;
372                                 }
373                         }
374                 }
375                 
376                 y-= ACHANNEL_STEP;
377         }
378         
379         /* free tempolary channels used for drawing */
380         BLI_freelistN(&anim_data);
381
382         /* black line marking 'current frame' for Time-Slide transform mode */
383         if (saction->flag & SACTION_MOVING) {
384                 glColor3f(0.0f, 0.0f, 0.0f);
385                 
386                 glBegin(GL_LINES);
387                         glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD);
388                         glVertex2f(saction->timeslide, v2d->cur.ymax);
389                 glEnd();
390         }
391 }