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