bug in DEG_OBJECT_ITER
[blender.git] / source / blender / editors / animation / anim_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Joshua Leung
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/animation/anim_draw.c
28  *  \ingroup edanimation
29  */
30
31 #include "BLI_sys_types.h"
32
33 #include "DNA_anim_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_userdef_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_gpencil_types.h"
40 #include "DNA_mask_types.h"
41
42 #include "BLI_math.h"
43 #include "BLI_timecode.h"
44 #include "BLI_utildefines.h"
45 #include "BLI_rect.h"
46 #include "BLI_dlrbTree.h"
47
48 #include "BKE_context.h"
49 #include "BKE_global.h"
50 #include "BKE_nla.h"
51 #include "BKE_mask.h"
52
53 #include "ED_anim_api.h"
54 #include "ED_keyframes_edit.h"
55 #include "ED_keyframes_draw.h"
56
57 #include "RNA_access.h"
58
59 #include "BIF_gl.h"
60
61 #include "UI_interface.h"
62 #include "UI_resources.h"
63 #include "UI_view2d.h"
64
65 #include "GPU_immediate.h"
66
67 /* *************************************************** */
68 /* CURRENT FRAME DRAWING */
69
70 /* Draw current frame number in a little green box beside the current frame indicator */
71 static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
72 {
73         const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
74         VertexFormat *format = immVertexFormat();
75         unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
76         unsigned char col[4];
77         float xscale, yscale, x, y;
78         char numstr[32] = "    t";  /* t is the character to start replacing from */
79         int slen;
80         
81         /* because the frame number text is subject to the same scaling as the contents of the view */
82         UI_view2d_scale_get(v2d, &xscale, &yscale);
83         glScalef(1.0f / xscale, 1.0f, 1.0f);
84         
85         /* get timecode string 
86          *      - padding on str-buf passed so that it doesn't sit on the frame indicator
87          *      - power = 0, gives 'standard' behavior for time
88          *        but power = 1 is required for frames (to get integer frames)
89          */
90         if (time) {
91                 BLI_timecode_string_from_time(&numstr[4], sizeof(numstr) - 4, 0, FRA2TIME(cfra), FPS, U.timecode_style);
92         }
93         else {
94                 BLI_timecode_string_from_time_seconds(&numstr[4], sizeof(numstr) - 4, 1, cfra);
95         }
96
97         slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
98         
99         /* get starting coordinates for drawing */
100         x = cfra * xscale;
101         y = 0.9f * U.widget_unit;
102
103         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
104
105         /* draw green box around/behind text */
106         immUniformThemeColorShade(TH_CFRAME, 0);
107
108         immRectf(pos, x, y,  x + slen,  y + 0.75f * U.widget_unit);
109         immUnbindProgram();
110
111         /* draw current frame number - black text */
112         UI_GetThemeColor4ubv(TH_TEXT, col);
113         UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr, col);
114
115         /* restore view transform */
116         glScalef(xscale, 1.0, 1.0);
117 }
118
119 /* General call for drawing current frame indicator in animation editor */
120 void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
121 {
122         Scene *scene = CTX_data_scene(C);
123
124         const float x = (float)(scene->r.cfra * scene->r.framelen);
125
126         glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
127
128         VertexFormat *format = immVertexFormat();
129         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
130
131         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
132
133         /* Draw a light green line to indicate current frame */
134         immUniformThemeColor(TH_CFRAME);
135
136         immBegin(GL_LINES, 2);
137         immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
138         immVertex2f(pos, x, v2d->cur.ymax);
139         immEnd();
140         immUnbindProgram();
141
142         /* Draw current frame number in a little box */
143         if (flag & DRAWCFRA_SHOW_NUMBOX) {
144                 UI_view2d_view_orthoSpecial(CTX_wm_region(C), v2d, 1);
145                 draw_cfra_number(scene, v2d, x, (flag & DRAWCFRA_UNIT_SECONDS) != 0);
146         }
147 }
148
149 /* *************************************************** */
150 /* PREVIEW RANGE 'CURTAINS' */
151 /* Note: 'Preview Range' tools are defined in anim_ops.c */
152
153 /* Draw preview range 'curtains' for highlighting where the animation data is */
154 void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
155 {
156         Scene *scene = CTX_data_scene(C);
157         
158         /* only draw this if preview range is set */
159         if (PRVRANGEON) {
160                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
161                 glEnable(GL_BLEND);
162
163                 VertexFormat *format = immVertexFormat();
164                 unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
165
166                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
167                 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
168
169                 /* only draw two separate 'curtains' if there's no overlap between them */
170                 if (PSFRA < PEFRA + end_frame_width) {
171                         immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
172                         immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
173                 }
174                 else {
175                         immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
176                 }
177
178                 immUnbindProgram();
179
180                 glDisable(GL_BLEND);
181         }
182 }
183
184 /* *************************************************** */
185 /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes)  */
186
187 /* Obtain the AnimData block providing NLA-mapping for the given channel (if applicable) */
188 // TODO: do not supply return this if the animdata tells us that there is no mapping to perform
189 AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
190 {
191         /* sanity checks */
192         if (ac == NULL)
193                 return NULL;
194         
195         /* abort if rendering - we may get some race condition issues... */
196         if (G.is_rendering) return NULL;
197         
198         /* apart from strictly keyframe-related contexts, this shouldn't even happen */
199         // XXX: nla and channel here may not be necessary...
200         if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_SHAPEKEY, ANIMCONT_DOPESHEET,
201                                ANIMCONT_FCURVES, ANIMCONT_NLA, ANIMCONT_CHANNEL))
202         {
203                 /* handling depends on the type of animation-context we've got */
204                 if (ale) {
205                         /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */
206                         if (ale->type != ANIMTYPE_NLACURVE)
207                                 return ale->adt;
208                 }
209         }
210         
211         /* cannot handle... */
212         return NULL;
213 }
214
215 /* ------------------- */
216
217 /* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */
218 static short bezt_nlamapping_restore(KeyframeEditData *ked, BezTriple *bezt)
219 {
220         /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
221         AnimData *adt = (AnimData *)ked->data;
222         short only_keys = (short)ked->i1;
223         
224         /* adjust BezTriple handles only if allowed to */
225         if (only_keys == 0) {
226                 bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP);
227                 bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP);
228         }
229         
230         bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP);
231         
232         return 0;
233 }
234
235 /* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */
236 static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt)
237 {
238         /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
239         AnimData *adt = (AnimData *)ked->data;
240         short only_keys = (short)ked->i1;
241         
242         /* adjust BezTriple handles only if allowed to */
243         if (only_keys == 0) {
244                 bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
245                 bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
246         }
247         
248         bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
249         
250         return 0;
251 }
252
253
254 /* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve 
255  *      - restore = whether to map points back to non-mapped time 
256  *  - only_keys = whether to only adjust the location of the center point of beztriples
257  */
258 void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
259 {
260         KeyframeEditData ked = {{NULL}};
261         KeyframeEditFunc map_cb;
262         
263         /* init edit data 
264          *      - AnimData is stored in 'data'
265          *      - only_keys is stored in 'i1'
266          */
267         ked.data = (void *)adt;
268         ked.i1 = (int)only_keys;
269         
270         /* get editing callback */
271         if (restore)
272                 map_cb = bezt_nlamapping_restore;
273         else
274                 map_cb = bezt_nlamapping_apply;
275         
276         /* apply to F-Curve */
277         ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, map_cb, NULL);
278 }
279
280 /* *************************************************** */
281 /* UNITS CONVERSION MAPPING (required for drawing and editing keyframes) */
282
283 /* Get flags used for normalization in ANIM_unit_mapping_get_factor. */
284 short ANIM_get_normalization_flags(bAnimContext *ac)
285 {
286         if (ac->sl->spacetype == SPACE_IPO) {
287                 SpaceIpo *sipo = (SpaceIpo *) ac->sl;
288                 bool use_normalization = (sipo->flag & SIPO_NORMALIZE) != 0;
289                 bool freeze_normalization = (sipo->flag & SIPO_NORMALIZE_FREEZE) != 0;
290                 return use_normalization
291                     ? (ANIM_UNITCONV_NORMALIZE |  (freeze_normalization ? ANIM_UNITCONV_NORMALIZE_FREEZE : 0))
292                     : 0;
293         }
294
295         return 0;
296 }
297
298 static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset)
299 {
300         float factor = 1.0f, offset = 0.0f;
301
302         if (flag & ANIM_UNITCONV_RESTORE) {
303                 if (r_offset)
304                         *r_offset = fcu->prev_offset;
305
306                 return 1.0f / fcu->prev_norm_factor;
307         }
308
309         if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
310                 if (r_offset)
311                         *r_offset = fcu->prev_offset;
312                 if (fcu->prev_norm_factor == 0.0f) {
313                         /* Happens when Auto Normalize was disabled before
314                          * any curves were displayed.
315                          */
316                         return 1.0f;
317                 }
318                 return fcu->prev_norm_factor;
319         }
320
321         if (G.moving & G_TRANSFORM_FCURVES) {
322                 if (r_offset)
323                         *r_offset = fcu->prev_offset;
324                 if (fcu->prev_norm_factor == 0.0f) {
325                         /* Same as above. */
326                         return 1.0f;
327                 }
328                 return fcu->prev_norm_factor;
329         }
330
331         fcu->prev_norm_factor = 1.0f;
332         if (fcu->bezt) {
333                 BezTriple *bezt;
334                 int i;
335                 float max_coord = -FLT_MAX;
336                 float min_coord = FLT_MAX;
337                 float range;
338
339                 if (fcu->totvert < 1) {
340                         return 1.0f;
341                 }
342
343                 if (PRVRANGEON) {
344                         for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
345                                 if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
346                                         max_coord = max_ff(max_coord, bezt->vec[0][1]);
347                                         max_coord = max_ff(max_coord, bezt->vec[1][1]);
348                                         max_coord = max_ff(max_coord, bezt->vec[2][1]);
349
350                                         min_coord = min_ff(min_coord, bezt->vec[0][1]);
351                                         min_coord = min_ff(min_coord, bezt->vec[1][1]);
352                                         min_coord = min_ff(min_coord, bezt->vec[2][1]);
353                                 }
354                         }
355                 }
356                 else {
357                         for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
358                                 max_coord = max_ff(max_coord, bezt->vec[0][1]);
359                                 max_coord = max_ff(max_coord, bezt->vec[1][1]);
360                                 max_coord = max_ff(max_coord, bezt->vec[2][1]);
361
362                                 min_coord = min_ff(min_coord, bezt->vec[0][1]);
363                                 min_coord = min_ff(min_coord, bezt->vec[1][1]);
364                                 min_coord = min_ff(min_coord, bezt->vec[2][1]);
365                         }
366                 }
367
368                 if (max_coord > min_coord) {
369                         range = max_coord - min_coord;
370                         if (range > FLT_EPSILON) {
371                                 factor = 2.0f / range;
372                         }
373                         offset = -min_coord - range / 2.0f;
374                 }
375                 else if (max_coord == min_coord) {
376                         factor = 1.0f;
377                         offset = -min_coord;
378                 }
379         }
380         BLI_assert(factor != 0.0f);
381         if (r_offset) {
382                 *r_offset = offset;
383         }
384
385         fcu->prev_norm_factor = factor;
386         fcu->prev_offset = offset;
387         return factor;
388 }
389
390 /* Get unit conversion factor for given ID + F-Curve */
391 float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
392 {
393         if (flag & ANIM_UNITCONV_NORMALIZE) {
394                 return normalization_factor_get(scene, fcu, flag, r_offset);
395         }
396
397         if (r_offset)
398                 *r_offset = 0.0f;
399
400         /* sanity checks */
401         if (id && fcu && fcu->rna_path) {
402                 PointerRNA ptr, id_ptr;
403                 PropertyRNA *prop;
404                 
405                 /* get RNA property that F-Curve affects */
406                 RNA_id_pointer_create(id, &id_ptr);
407                 if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
408                         /* rotations: radians <-> degrees? */
409                         if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
410                                 /* if the radians flag is not set, default to using degrees which need conversions */
411                                 if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) {
412                                         if (flag & ANIM_UNITCONV_RESTORE)
413                                                 return DEG2RADF(1.0f);  /* degrees to radians */
414                                         else
415                                                 return RAD2DEGF(1.0f);  /* radians to degrees */
416                                 }
417                         }
418                         
419                         /* TODO: other rotation types here as necessary */
420                 }
421         }
422
423         /* no mapping needs to occur... */
424         return 1.0f;
425 }
426
427 static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
428 {
429         Scene *scene = CTX_data_scene(C);
430         Object *ob = CTX_data_active_object(C);
431         Mask *mask = CTX_data_edit_mask(C);
432         bDopeSheet ads = {NULL};
433         DLRBT_Tree keys;
434         ActKeyColumn *aknext, *akprev;
435         float cfranext, cfraprev;
436         bool donenext = false, doneprev = false;
437         int nextcount = 0, prevcount = 0;
438
439         cfranext = cfraprev = (float)(CFRA);
440
441         /* init binarytree-list for getting keyframes */
442         BLI_dlrbTree_init(&keys);
443
444         /* seed up dummy dopesheet context with flags to perform necessary filtering */
445         if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
446                 /* only selected channels are included */
447                 ads.filterflag |= ADS_FILTER_ONLYSEL;
448         }
449
450         /* populate tree with keyframe nodes */
451         scene_to_keylist(&ads, scene, &keys, NULL);
452         gpencil_to_keylist(&ads, scene->gpd, &keys);
453
454         if (ob) {
455                 ob_to_keylist(&ads, ob, &keys, NULL);
456                 gpencil_to_keylist(&ads, ob->gpd, &keys);
457         }
458
459         if (mask) {
460                 MaskLayer *masklay = BKE_mask_layer_active(mask);
461                 mask_to_keylist(&ads, masklay, &keys);
462         }
463
464         /* build linked-list for searching */
465         BLI_dlrbTree_linkedlist_sync(&keys);
466
467         /* find matching keyframe in the right direction */
468         do {
469                 aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);
470
471                 if (aknext) {
472                         if (CFRA == (int)aknext->cfra) {
473                                 /* make this the new starting point for the search and ignore */
474                                 cfranext = aknext->cfra;
475                         }
476                         else {
477                                 /* this changes the frame, so set the frame and we're done */
478                                 if (++nextcount == U.view_frame_keyframes)
479                                         donenext = true;
480                         }
481                         cfranext = aknext->cfra;
482                 }
483         } while ((aknext != NULL) && (donenext == false));
484
485         do {
486                 akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);
487
488                 if (akprev) {
489                         if (CFRA == (int)akprev->cfra) {
490                                 /* make this the new starting point for the search */
491                         }
492                         else {
493                                 /* this changes the frame, so set the frame and we're done */
494                                 if (++prevcount == U.view_frame_keyframes)
495                                         doneprev = true;
496                         }
497                         cfraprev = akprev->cfra;
498                 }
499         } while ((akprev != NULL) && (doneprev == false));
500
501         /* free temp stuff */
502         BLI_dlrbTree_free(&keys);
503
504         /* any success? */
505         if (doneprev || donenext) {
506                 if (doneprev)
507                         *prevfra = cfraprev;
508                 else
509                         *prevfra = CFRA - (cfranext - CFRA);
510
511                 if (donenext)
512                         *nextfra = cfranext;
513                 else
514                         *nextfra = CFRA + (CFRA - cfraprev);
515
516                 return true;
517         }
518
519         return false;
520 }
521
522 void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
523 {
524         ARegion *ar = CTX_wm_region(C);
525         Scene *scene = CTX_data_scene(C);
526         float w = BLI_rctf_size_x(&ar->v2d.cur);
527         rctf newrct;
528         int nextfra, prevfra;
529
530         switch (U.view_frame_type) {
531                 case ZOOM_FRAME_MODE_SECONDS:
532                 {
533                         const float fps = FPS;
534                         newrct.xmax = scene->r.cfra + U.view_frame_seconds * fps + 1;
535                         newrct.xmin = scene->r.cfra - U.view_frame_seconds * fps - 1;
536                         newrct.ymax = ar->v2d.cur.ymax;
537                         newrct.ymin = ar->v2d.cur.ymin;
538                         break;
539                 }
540
541                 /* hardest case of all, look for all keyframes around frame and display those */
542                 case ZOOM_FRAME_MODE_KEYFRAMES:
543                         if (find_prev_next_keyframes(C, &nextfra, &prevfra)) {
544                                 newrct.xmax = nextfra;
545                                 newrct.xmin = prevfra;
546                                 newrct.ymax = ar->v2d.cur.ymax;
547                                 newrct.ymin = ar->v2d.cur.ymin;
548                                 break;
549                         }
550                         /* else drop through, keep range instead */
551
552                 case ZOOM_FRAME_MODE_KEEP_RANGE:
553                 default:
554                         newrct.xmax = scene->r.cfra + (w / 2);
555                         newrct.xmin = scene->r.cfra - (w / 2);
556                         newrct.ymax = ar->v2d.cur.ymax;
557                         newrct.ymin = ar->v2d.cur.ymin;
558                         break;
559         }
560
561         UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
562 }
563 /* *************************************************** */