svn merge -r 30954:31059 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / editors / space_view3d / drawanimviz.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 by the Blender Foundation.
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 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_anim_types.h"
37 #include "DNA_armature_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_view3d_types.h"
41 #include "DNA_object_types.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_math.h"
45 #include "BLI_dlrbTree.h"
46
47 #include "BKE_animsys.h"
48 #include "BKE_action.h"
49 #include "BKE_armature.h"
50 #include "BKE_constraint.h"
51 #include "BKE_context.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_global.h"
55 #include "BKE_main.h"
56 #include "BKE_modifier.h"
57 #include "BKE_nla.h"
58 #include "BKE_object.h"
59 #include "BKE_utildefines.h"
60
61 #include "BIF_gl.h"
62 #include "BIF_glutil.h"
63
64 #include "ED_armature.h"
65 #include "ED_keyframes_draw.h"
66
67 #include "BLF_api.h"
68
69 #include "UI_resources.h"
70
71 #include "view3d_intern.h"
72
73 /* ************************************ Motion Paths ************************************* */
74
75 // TODO: 
76 //      - options to draw paths with lines
77 //      - include support for editing the path verts
78
79 /* Set up drawing environment for drawing motion paths */
80 void draw_motion_paths_init(Scene *scene, View3D *v3d, ARegion *ar) 
81 {
82         RegionView3D *rv3d= ar->regiondata;
83         
84         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
85         
86         glPushMatrix();
87         glLoadMatrixf(rv3d->viewmat);
88 }
89
90 /* Draw the given motion path for an Object or a Bone 
91  *      - assumes that the viewport has already been initialised properly
92  *              i.e. draw_motion_paths_init() has been called
93  */
94 // FIXME: the text is still drawn in the wrong space - it includes the current transforms of the object still...
95 void draw_motion_path_instance(Scene *scene, View3D *v3d, ARegion *ar, 
96                         Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
97 {
98         //RegionView3D *rv3d= ar->regiondata;
99         bMotionPathVert *mpv, *mpv_start;
100         int i, stepsize= avs->path_step;
101         int sfra, efra, len;
102         
103         
104         /* get frame ranges */
105         if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
106                 int sind;
107                 
108                 /* With "Around Current", we only choose frames from around 
109                  * the current frame to draw. However, this range is still 
110                  * restricted by the limits of the original path.
111                  */
112                 sfra= CFRA - avs->path_bc;
113                 efra= CFRA + avs->path_ac;
114                 if (sfra < mpath->start_frame) sfra= mpath->start_frame;
115                 if (efra > mpath->end_frame) efra= mpath->end_frame;
116                 
117                 len= efra - sfra;
118                 
119                 sind= sfra - mpath->start_frame;
120                 mpv_start= (mpath->points + sind);
121         }
122         else {
123                 sfra= mpath->start_frame;
124                 efra = sfra + mpath->length;
125                 len = mpath->length;
126                 mpv_start= mpath->points;
127         }
128         
129         /* draw curve-line of path */
130         glShadeModel(GL_SMOOTH);
131         
132         glBegin(GL_LINE_STRIP);                                 
133         for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
134                 short sel= (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
135                 float intensity; /* how faint */
136                 
137                 /* set color
138                  *      - more intense for active/selected bones, less intense for unselected bones
139                  *      - black for before current frame, green for current frame, blue for after current frame
140                  *      - intensity decreases as distance from current frame increases
141                  */
142                 #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min) 
143                 if ((sfra+i) < CFRA) {
144                         /* black - before cfra */
145                         if (sel) {
146                                 // intensity= 0.5f;
147                                 intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
148                         }
149                         else {
150                                 //intensity= 0.8f;
151                                 intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
152                         }
153                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity);
154                 }
155                 else if ((sfra+i) > CFRA) {
156                         /* blue - after cfra */
157                         if (sel) {
158                                 //intensity = 0.5f;
159                                 intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
160                         }
161                         else {
162                                 //intensity = 0.8f;
163                                 intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
164                         }
165                         UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity);
166                 }
167                 else {
168                         /* green - on cfra */
169                         if (sel) {
170                                 intensity= 0.5f;
171                         }
172                         else {
173                                 intensity= 0.99f;
174                         }
175                         UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
176                 }       
177                 
178                 /* draw a vertex with this color */ 
179                 glVertex3fv(mpv->co);
180         }
181         
182         glEnd();
183         glShadeModel(GL_FLAT);
184         
185         glPointSize(1.0);
186         
187         /* draw little black point at each frame
188          * NOTE: this is not really visible/noticable
189          */
190         glBegin(GL_POINTS);
191         for (i=0, mpv=mpv_start; i < len; i++, mpv++) 
192                 glVertex3fv(mpv->co);
193         glEnd();
194         
195         /* Draw little white dots at each framestep value */
196         UI_ThemeColor(TH_TEXT_HI);
197         glBegin(GL_POINTS);
198         for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) 
199                 glVertex3fv(mpv->co);
200         glEnd();
201         
202         /* Draw big green dot where the current frame is */
203         // NOTE: only do this when drawing keyframes for now... 
204         if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
205                 UI_ThemeColor(TH_CFRAME);
206                 glPointSize(6.0f);
207                 
208                 glBegin(GL_POINTS);
209                         mpv = mpv_start + (CFRA - sfra);
210                         glVertex3fv(mpv->co);
211                 glEnd();
212                 
213                 glPointSize(1.0f);
214                 UI_ThemeColor(TH_TEXT_HI);
215         }
216         
217         /* Draw frame numbers at each framestep value */
218         if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
219                 for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) {
220                         char str[32];
221                         
222                         /* only draw framenum if several consecutive highlighted points don't occur on same point */
223                         if (i == 0) {
224                                 sprintf(str, "%d", (i+sfra));
225                                 view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0, 0);
226                         }
227                         else if ((i > stepsize) && (i < len-stepsize)) { 
228                                 bMotionPathVert *mpvP = (mpv - stepsize);
229                                 bMotionPathVert *mpvN = (mpv + stepsize);
230                                 
231                                 if ((equals_v3v3(mpv->co, mpvP->co)==0) || (equals_v3v3(mpv->co, mpvN->co)==0)) {
232                                         sprintf(str, "%d", (sfra+i));
233                                         view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0, 0);
234                                 }
235                         }
236                 }
237         }
238         
239         /* Keyframes - dots and numbers */
240         if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
241                 AnimData *adt= BKE_animdata_from_id(&ob->id);
242                 DLRBT_Tree keys;
243                 
244                 /* build list of all keyframes in active action for object or pchan */
245                 BLI_dlrbTree_init(&keys);
246                 
247                 if (adt) {
248                         /* it is assumed that keyframes for bones are all grouped in a single group
249                          * unless an option is set to always use the whole action
250                          */
251                         if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT)==0) {
252                                 bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name);
253                                 
254                                 if (agrp) {
255                                         agroup_to_keylist(adt, agrp, &keys, NULL);
256                                         BLI_dlrbTree_linkedlist_sync(&keys);
257                                 }
258                         }
259                         else {
260                                 action_to_keylist(adt, adt->action, &keys, NULL);
261                                 BLI_dlrbTree_linkedlist_sync(&keys);
262                         }
263                 }
264                 
265                 /* Draw slightly-larger yellow dots at each keyframe */
266                 UI_ThemeColor(TH_VERTEX_SELECT);
267                 glPointSize(4.0f); // XXX perhaps a bit too big
268                 
269                 glBegin(GL_POINTS);
270                 for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
271                         float mframe= (float)(sfra + i);
272                         
273                         if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
274                                 glVertex3fv(mpv->co);
275                 }
276                 glEnd();
277                 
278                 glPointSize(1.0f);
279                 
280                 /* Draw frame numbers of keyframes  */
281                 if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
282                         for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
283                                 float mframe= (float)(sfra + i);
284                                 
285                                 if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
286                                         char str[32];
287                                         
288                                         sprintf(str, "%d", (sfra+i));
289                                         view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0, 0);
290                                 }
291                         }
292                 }
293                 
294                 BLI_dlrbTree_free(&keys);
295         }
296 }
297
298 /* Clean up drawing environment after drawing motion paths */
299 void draw_motion_paths_cleanup(Scene *scene, View3D *v3d, ARegion *ar)
300 {
301         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
302         glPopMatrix();
303 }
304
305 #if 0 // XXX temp file guards 
306
307 /* ***************************** Onion Skinning (Ghosts) ******************************** */
308
309 #if 0 // XXX only for bones
310 /* helper function for ghost drawing - sets/removes flags for temporarily 
311  * hiding unselected bones while drawing ghosts
312  */
313 static void ghost_poses_tag_unselected(Object *ob, short unset)
314 {
315         bArmature *arm= ob->data;
316         bPose *pose= ob->pose;
317         bPoseChannel *pchan;
318         
319         /* don't do anything if no hiding any bones */
320         if ((arm->flag & ARM_GHOST_ONLYSEL)==0)
321                 return;
322                 
323         /* loop over all pchans, adding/removing tags as appropriate */
324         for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
325                 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
326                         if (unset) {
327                                 /* remove tags from all pchans if cleaning up */
328                                 pchan->bone->flag &= ~BONE_HIDDEN_PG;
329                         }
330                         else {
331                                 /* set tags on unselected pchans only */
332                                 if ((pchan->bone->flag & BONE_SELECTED)==0)
333                                         pchan->bone->flag |= BONE_HIDDEN_PG;
334                         }
335                 }
336         }
337 }
338 #endif // XXX only for bones
339
340 /* draw ghosts that occur within a frame range 
341  *      note: object should be in posemode 
342  */
343 static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
344 {
345         Object *ob= base->object;
346         AnimData *adt= BKE_animdata_from_id(&ob->id);
347         bArmature *arm= ob->data;
348         bPose *posen, *poseo;
349         float start, end, stepsize, range, colfac;
350         int cfrao, flago, ipoflago;
351         
352         start = (float)arm->ghostsf;
353         end = (float)arm->ghostef;
354         if (end <= start)
355                 return;
356         
357         stepsize= (float)(arm->ghostsize);
358         range= (float)(end - start);
359         
360         /* store values */
361         ob->mode &= ~OB_MODE_POSE;
362         cfrao= CFRA;
363         flago= arm->flag;
364         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
365         ipoflago= ob->ipoflag; 
366         ob->ipoflag |= OB_DISABLE_PATH;
367         
368         /* copy the pose */
369         poseo= ob->pose;
370         copy_pose(&posen, ob->pose, 1);
371         ob->pose= posen;
372         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
373         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
374         
375         glEnable(GL_BLEND);
376         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
377         
378         /* draw from first frame of range to last */
379         for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) {
380                 colfac = (end - (float)CFRA) / range;
381                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
382                 
383                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
384                 where_is_pose(scene, ob);
385                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
386         }
387         glDisable(GL_BLEND);
388         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
389
390         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
391         free_pose(posen);
392         
393         /* restore */
394         CFRA= cfrao;
395         ob->pose= poseo;
396         arm->flag= flago;
397         armature_rebuild_pose(ob, ob->data);
398         ob->mode |= OB_MODE_POSE;
399         ob->ipoflag= ipoflago; 
400 }
401
402 /* draw ghosts on keyframes in action within range 
403  *      - object should be in posemode 
404  */
405 static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
406 {
407         Object *ob= base->object;
408         AnimData *adt= BKE_animdata_from_id(&ob->id);
409         bAction *act= (adt) ? adt->action : NULL;
410         bArmature *arm= ob->data;
411         bPose *posen, *poseo;
412         DLRBT_Tree keys;
413         ActKeyColumn *ak, *akn;
414         float start, end, range, colfac, i;
415         int cfrao, flago;
416         
417         start = (float)arm->ghostsf;
418         end = (float)arm->ghostef;
419         if (end <= start)
420                 return;
421         
422         /* get keyframes - then clip to only within range */
423         BLI_dlrbTree_init(&keys);
424         action_to_keylist(adt, act, &keys, NULL);
425         BLI_dlrbTree_linkedlist_sync(&keys);
426         
427         range= 0;
428         for (ak= keys.first; ak; ak= akn) {
429                 akn= ak->next;
430                 
431                 if ((ak->cfra < start) || (ak->cfra > end))
432                         BLI_freelinkN((ListBase *)&keys, ak);
433                 else
434                         range++;
435         }
436         if (range == 0) return;
437         
438         /* store values */
439         ob->mode &= ~OB_MODE_POSE;
440         cfrao= CFRA;
441         flago= arm->flag;
442         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
443         ob->ipoflag |= OB_DISABLE_PATH;
444         
445         /* copy the pose */
446         poseo= ob->pose;
447         copy_pose(&posen, ob->pose, 1);
448         ob->pose= posen;
449         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
450         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
451         
452         glEnable(GL_BLEND);
453         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
454         
455         /* draw from first frame of range to last */
456         for (ak=keys.first, i=0; ak; ak=ak->next, i++) {
457                 colfac = i/range;
458                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
459                 
460                 CFRA= (int)ak->cfra;
461                 
462                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
463                 where_is_pose(scene, ob);
464                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
465         }
466         glDisable(GL_BLEND);
467         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
468
469         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
470         BLI_dlrbTree_free(&keys);
471         free_pose(posen);
472         
473         /* restore */
474         CFRA= cfrao;
475         ob->pose= poseo;
476         arm->flag= flago;
477         armature_rebuild_pose(ob, ob->data);
478         ob->mode |= OB_MODE_POSE;
479 }
480
481 /* draw ghosts around current frame
482  *      - object is supposed to be armature in posemode 
483  */
484 static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
485 {
486         Object *ob= base->object;
487         AnimData *adt= BKE_animdata_from_id(&ob->id);
488         bArmature *arm= ob->data;
489         bPose *posen, *poseo;
490         float cur, start, end, stepsize, range, colfac, actframe, ctime;
491         int cfrao, flago;
492         
493         /* pre conditions, get an action with sufficient frames */
494         if ELEM(NULL, adt, adt->action)
495                 return;
496
497         calc_action_range(adt->action, &start, &end, 0);
498         if (start == end)
499                 return;
500
501         stepsize= (float)(arm->ghostsize);
502         range= (float)(arm->ghostep)*stepsize + 0.5f;   /* plus half to make the for loop end correct */
503         
504         /* store values */
505         ob->mode &= ~OB_MODE_POSE;
506         cfrao= CFRA;
507         actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
508         flago= arm->flag;
509         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
510         
511         /* copy the pose */
512         poseo= ob->pose;
513         copy_pose(&posen, ob->pose, 1);
514         ob->pose= posen;
515         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
516         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
517         
518         glEnable(GL_BLEND);
519         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
520         
521         /* draw from darkest blend to lowest */
522         for(cur= stepsize; cur<range; cur+=stepsize) {
523                 ctime= cur - (float)fmod(cfrao, stepsize);      /* ensures consistent stepping */
524                 colfac= ctime/range;
525                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
526                 
527                 /* only within action range */
528                 if (actframe+ctime >= start && actframe+ctime <= end) {
529                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
530                         
531                         if (CFRA != cfrao) {
532                                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
533                                 where_is_pose(scene, ob);
534                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
535                         }
536                 }
537                 
538                 ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f;       /* ensures consistent stepping */
539                 colfac= ctime/range;
540                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
541                 
542                 /* only within action range */
543                 if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
544                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
545                         
546                         if (CFRA != cfrao) {
547                                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
548                                 where_is_pose(scene, ob);
549                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
550                         }
551                 }
552         }
553         glDisable(GL_BLEND);
554         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
555
556         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
557         free_pose(posen);
558         
559         /* restore */
560         CFRA= cfrao;
561         ob->pose= poseo;
562         arm->flag= flago;
563         armature_rebuild_pose(ob, ob->data);
564         ob->mode |= OB_MODE_POSE;
565 }
566
567
568
569 #endif // XXX temp file guards