Initial revision
[blender.git] / source / blender / src / drawview.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 //#define NAN_LINEAR_PHYSICS
34
35 #include <math.h>
36 #ifndef WIN32
37 #include <unistd.h>
38 #include <sys/times.h>
39 #else
40 #include <io.h>
41 #include "BLI_winstuff.h"
42 #endif   
43
44 #include "MEM_guardedalloc.h"
45
46 #include "PIL_time.h"
47
48 #include "BMF_Api.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52 #include "BLI_editVert.h"
53
54 #include "IMB_imbuf_types.h"
55
56 #include "DNA_object_types.h"
57 #include "DNA_constraint_types.h"
58 #include "DNA_group_types.h"
59 #include "DNA_image_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_texture_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_userdef_types.h"
64
65 #include "BKE_action.h"
66 #include "BKE_anim.h"
67 #include "BKE_constraint.h"
68 #include "BKE_displist.h"
69 #include "BKE_global.h"
70 #include "BKE_ika.h"
71 #include "BKE_image.h"
72 #include "BKE_ipo.h"
73 #include "BKE_key.h"
74 #include "BKE_main.h"
75 #include "BKE_object.h"
76 #include "BKE_texture.h"
77 #include "BKE_utildefines.h"
78
79 #include "BIF_gl.h"
80 #include "BIF_resources.h"
81 #include "BIF_screen.h"
82 #include "BIF_interface.h"
83 #include "BIF_space.h"
84 #include "BIF_buttons.h"
85 #include "BIF_drawimage.h"
86 #include "BIF_editgroup.h"
87 #include "BIF_mywindow.h"
88
89 #include "BDR_drawmesh.h"
90 #include "BDR_drawobject.h"
91
92 #include "BSE_view.h"
93 #include "BSE_drawview.h"
94 #include "BSE_headerbuttons.h"
95
96 #include "RE_renderconverter.h"
97
98 #include "BPY_extern.h" // Blender Python library
99
100 #include "interface.h"
101 #include "blendef.h"
102 #include "mydevice.h"
103
104 /* Modules used */
105 #include "render.h"
106 #include "radio.h"
107
108 /* for physics in animation playback */
109 #ifdef NAN_LINEAR_PHYSICS
110 #include "sumo.h"
111 #endif
112
113 /* locals */
114 void drawname(Object *ob);
115 void star_stuff_init_func(void);
116 void star_stuff_vertex_func(float* i);
117 void star_stuff_term_func(void);
118
119 void star_stuff_init_func(void)
120 {
121         cpack(-1);
122         glPointSize(1.0);
123         glBegin(GL_POINTS);
124 }
125 void star_stuff_vertex_func(float* i)
126 {
127         glVertex3fv(i);
128 }
129 void star_stuff_term_func(void)
130 {
131         glEnd();
132 }
133
134 void setalpha_bgpic(BGpic *bgpic)
135 {
136         int x, y, alph;
137         char *rect;
138         
139         alph= (int)(255.0*(1.0-bgpic->blend));
140         
141         rect= (char *)bgpic->rect;
142         for(y=0; y< bgpic->yim; y++) {
143                 for(x= bgpic->xim; x>0; x--, rect+=4) {
144                         rect[3]= alph;
145                 }
146         }
147 }
148
149
150 static float light_pos1[] = { -0.3, 0.3, 0.90, 0.0 }; 
151 /*  static float light_pos2[] = { 0.3, -0.3, -0.90, 0.0 };  never used? */
152
153 void default_gl_light(void)
154 {
155         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
156         float light_col1[] = { 0.8, 0.8, 0.8, 0.0 }; 
157
158         int a;
159                 
160         glLightfv(GL_LIGHT0, GL_POSITION, light_pos1); 
161         glLightfv(GL_LIGHT0, GL_DIFFUSE, light_col1); 
162         glLightfv(GL_LIGHT0, GL_SPECULAR, mat_specular); 
163
164         glEnable(GL_LIGHT0);
165         for(a=1; a<8; a++) glDisable(GL_LIGHT0+a);
166         glDisable(GL_LIGHTING);
167
168         glDisable(GL_COLOR_MATERIAL);
169 }
170
171 void init_gl_stuff(void)        
172 {
173         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
174         float mat_shininess[] = { 35.0 };
175 /*      float one= 1.0; */
176         int a, x, y;
177         GLubyte pat[32*32];
178         const GLubyte *patc= pat;
179                 
180         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
181         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
182         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
183
184         default_gl_light();
185         
186         /* no local viewer, looks ugly in ortho mode */
187         /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
188         
189         glDepthFunc(GL_LEQUAL);
190         /* scaling matrices */
191         glEnable(GL_NORMALIZE);
192
193         glShadeModel(GL_FLAT);
194
195         glDisable(GL_ALPHA_TEST);
196         glDisable(GL_BLEND);
197         glDisable(GL_DEPTH_TEST);
198         glDisable(GL_FOG);
199         glDisable(GL_LIGHTING);
200         glDisable(GL_LOGIC_OP);
201         glDisable(GL_STENCIL_TEST);
202         glDisable(GL_TEXTURE_1D);
203         glDisable(GL_TEXTURE_2D);
204
205         glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
206         glPixelTransferi(GL_RED_SCALE, 1);
207         glPixelTransferi(GL_RED_BIAS, 0);
208         glPixelTransferi(GL_GREEN_SCALE, 1);
209         glPixelTransferi(GL_GREEN_BIAS, 0);
210         glPixelTransferi(GL_BLUE_SCALE, 1);
211         glPixelTransferi(GL_BLUE_BIAS, 0);
212         glPixelTransferi(GL_ALPHA_SCALE, 1);
213         glPixelTransferi(GL_ALPHA_BIAS, 0);
214
215         a= 0;
216         for(x=0; x<32; x++) {
217                 for(y=0; y<4; y++) {
218                         if( (x) & 1) pat[a++]= 0x88;
219                         else pat[a++]= 0x22;
220                 }
221         }
222         
223         glPolygonStipple(patc);
224
225
226         init_realtime_GL();     
227 }
228
229 void two_sided(int val)
230 {
231
232         /* twosided aan: geft errors bij x flip! */
233         glLightModeliv(GL_LIGHT_MODEL_TWO_SIDE, (GLint *)&val);
234 }
235
236 void circf(float x, float y, float rad)
237 {
238         GLUquadricObj *qobj = gluNewQuadric(); 
239         
240         gluQuadricDrawStyle(qobj, GLU_FILL); 
241         
242         glPushMatrix(); 
243         
244         glTranslatef(x,  y, 0.); 
245         
246         gluDisk( qobj, 0.0,  rad, 32, 1); 
247         
248         glPopMatrix(); 
249         
250         gluDeleteQuadric(qobj);
251 }
252
253 void circ(float x, float y, float rad)
254 {
255         GLUquadricObj *qobj = gluNewQuadric(); 
256         
257         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
258         
259         glPushMatrix(); 
260         
261         glTranslatef(x,  y, 0.); 
262         
263         gluDisk( qobj, 0.0,  rad, 32, 1); 
264         
265         glPopMatrix(); 
266         
267         gluDeleteQuadric(qobj);
268 }
269
270 /* ********** IN ONTWIKKELING ********** */
271
272 static void draw_bgpic(void)
273 {
274         BGpic *bgpic;
275         Image *ima;
276         float vec[3], fac, asp, zoomx, zoomy;
277         int x1, y1, x2, y2, cx, cy;
278         short mval[2];
279         
280         bgpic= G.vd->bgpic;
281         if(bgpic==0) return;
282         
283         if(bgpic->tex) {
284                 init_render_texture(bgpic->tex);
285                 free_unused_animimages();
286                 ima= bgpic->tex->ima;
287                 end_render_texture(bgpic->tex);
288         }
289         else {
290                 ima= bgpic->ima;
291         }
292         
293         if(ima==0) return;
294         if(ima->ok==0) return;
295         
296         /* plaatje testen */
297         if(ima->ibuf==0) {
298         
299                 if(bgpic->rect) MEM_freeN(bgpic->rect);
300                 bgpic->rect= 0;
301                 
302                 if(bgpic->tex) {
303                         ima_ibuf_is_nul(bgpic->tex);
304                 }
305                 else {
306                         waitcursor(1);
307                         load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
308                         waitcursor(0);
309                 }
310                 if(ima->ibuf==0) {
311                         ima->ok= 0;
312                         return;
313                 }
314         }
315
316         if(bgpic->rect==0) {
317                 
318                 bgpic->rect= MEM_dupallocN(ima->ibuf->rect);
319                 bgpic->xim= ima->ibuf->x;
320                 bgpic->yim= ima->ibuf->y;
321                 setalpha_bgpic(bgpic);
322         }
323
324         if(G.vd->persp==2) {
325                 rcti vb;
326
327                 calc_viewborder(G.vd, &vb);
328
329                 x1= vb.xmin;
330                 y1= vb.ymin;
331                 x2= vb.xmax;
332                 y2= vb.ymax;
333         }
334         else {
335                 /* windowco berekenen */
336                 initgrabz(0.0, 0.0, 0.0);
337                 window_to_3d(vec, 1, 0);
338                 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
339                 fac= 1.0/fac;
340         
341                 asp= ( (float)ima->ibuf->y)/(float)ima->ibuf->x;
342         
343                 vec[0]= vec[1]= vec[2]= 0.0;
344                 project_short_noclip(vec, mval);
345                 cx= mval[0];
346                 cy= mval[1];
347         
348                 x1=  cx+ fac*(bgpic->xof-bgpic->size);
349                 y1=  cy+ asp*fac*(bgpic->yof-bgpic->size);
350                 x2=  cx+ fac*(bgpic->xof+bgpic->size);
351                 y2=  cy+ asp*fac*(bgpic->yof+bgpic->size);
352         }
353         
354         /* volledige clip? */
355         
356         if(x2 < 0 ) return;
357         if(y2 < 0 ) return;
358         if(x1 > curarea->winx ) return;
359         if(y1 > curarea->winy ) return;
360         
361         zoomx= x2-x1;
362         zoomx /= (float)ima->ibuf->x;
363         zoomy= y2-y1;
364         zoomy /= (float)ima->ibuf->y;
365
366         glEnable(GL_BLEND);
367         if(G.zbuf) glDisable(GL_DEPTH_TEST);
368
369         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
370          
371         rectwrite_part(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winrct.xmax, curarea->winrct.ymax, 
372                    x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, ima->ibuf->x, ima->ibuf->y, zoomx, zoomy, bgpic->rect);
373
374         glBlendFunc(GL_ONE,  GL_ZERO); 
375         glDisable(GL_BLEND);
376         if(G.zbuf) glEnable(GL_DEPTH_TEST);
377          
378 }
379
380 void timestr(double time, char *str)
381 {
382         /* formaat 00:00:00.00 (hr:min:sec) string moet 12 lang */
383         int  hr= (int)      time/(60*60);
384         int min= (int) fmod(time/60, 60.0);
385         int sec= (int) fmod(time, 60.0);
386         int hun= (int) fmod(time*100.0, 100.0);
387
388         if (hr) {
389                 sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
390         } else {
391                 sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
392         }
393
394         str[11]=0;
395 }
396
397
398 static void drawgrid(void)
399 {
400         /* extern short bgpicmode; */
401         float wx, wy, x, y, fw, fx, fy, dx;
402         float vec4[4];
403
404         vec4[0]=vec4[1]=vec4[2]=0.0; 
405         vec4[3]= 1.0;
406         Mat4MulVec4fl(G.vd->persmat, vec4);
407         fx= vec4[0]; 
408         fy= vec4[1]; 
409         fw= vec4[3];
410
411         wx= (curarea->winx/2.0);        /* ivm afrondfoutjes, grid op verkeerde plek */
412         wy= (curarea->winy/2.0);
413
414         x= (wx)*fx/fw;
415         y= (wy)*fy/fw;
416
417         vec4[0]=vec4[1]=G.vd->grid; 
418         vec4[2]= 0.0;
419         vec4[3]= 1.0;
420         Mat4MulVec4fl(G.vd->persmat, vec4);
421         fx= vec4[0]; 
422         fy= vec4[1]; 
423         fw= vec4[3];
424
425         dx= fabs(x-(wx)*fx/fw);
426         if(dx==0) dx= fabs(y-(wy)*fy/fw);
427
428         if(dx<6.0) {
429                 dx*= 10.0;
430                 setlinestyle(3);
431                 if(dx<6.0) {
432                         dx*= 10.0;
433                         if(dx<6.0) {
434                                 setlinestyle(0);
435                                 return;
436                         }
437                 }
438         }
439         
440         persp(0);
441
442         cpack(0x484848);
443         
444         x+= (wx); 
445         y+= (wy);
446         fx= x/dx;
447         fx= x-dx*floor(fx);
448         
449         while(fx< curarea->winx) {
450                 fdrawline(fx,  0.0,  fx,  (float)curarea->winy); 
451                 fx+= dx; 
452         }
453
454         fy= y/dx;
455         fy= y-dx*floor(fy);
456         
457
458         while(fy< curarea->winy) {
459                 fdrawline(0.0,  fy,  (float)curarea->winx,  fy); 
460                 fy+= dx;
461         }
462
463         /* kruis in midden */
464         if(G.vd->view==3) cpack(0xA0D0A0); /* y-as */
465         else cpack(0xA0A0D0);   /* x-as */
466
467         fdrawline(0.0,  y,  (float)curarea->winx,  y); 
468         
469         if(G.vd->view==7) cpack(0xA0D0A0);      /* y-as */
470         else cpack(0xE0A0A0);   /* z-as */
471
472         fdrawline(x,  0.0,  x,  (float)curarea->winy); 
473
474         persp(1);
475         setlinestyle(0);
476 }
477
478
479 static void drawfloor(void)
480 {
481         View3D *vd;
482         float vert[3], grid;
483         int a, gridlines;
484         
485         vd= curarea->spacedata.first;
486
487         vert[2]= 0.0;
488
489         if(vd->gridlines<3) return;
490
491         gridlines= vd->gridlines/2;
492         grid= gridlines*vd->grid;
493         
494         cpack(0x484848);
495
496         for(a= -gridlines;a<=gridlines;a++) {
497
498                 if(a==0) {
499                         if(vd->persp==0) cpack(0xA0D0A0);
500                         else cpack(0x402000);
501                 }
502                 else if(a==1) {
503                         cpack(0x484848);
504                 }
505                 
506         
507                 glBegin(GL_LINE_STRIP);
508         vert[0]= a*vd->grid;
509         vert[1]= grid;
510         glVertex3fv(vert);
511         vert[1]= -grid;
512         glVertex3fv(vert);
513                 glEnd();
514         }
515         
516         cpack(0x484848);
517         
518         for(a= -gridlines;a<=gridlines;a++) {
519                 if(a==0) {
520                         if(vd->persp==0) cpack(0xA0A0D0);
521                         else cpack(0);
522                 }
523                 else if(a==1) {
524                         cpack(0x484848);
525                 }
526         
527                 glBegin(GL_LINE_STRIP);
528         vert[1]= a*vd->grid;
529         vert[0]= grid;
530         glVertex3fv(vert );
531         vert[0]= -grid;
532         glVertex3fv(vert);
533                 glEnd();
534         }
535
536 }
537
538 static void drawcursor(void)
539 {
540
541         if(G.f & G_PLAYANIM) return;
542         
543         project_short( give_cursor(), &G.vd->mx);
544
545         G.vd->mxo= G.vd->mx;
546         G.vd->myo= G.vd->my;
547
548         if( G.vd->mx!=3200) {
549                 
550                 setlinestyle(0); 
551                 cpack(0xFF);
552                 circ((float)G.vd->mx, (float)G.vd->my, 10.0);
553                 setlinestyle(4); 
554                 cpack(0xFFFFFF);
555                 circ((float)G.vd->mx, (float)G.vd->my, 10.0);
556                 setlinestyle(0);
557                 cpack(0x0);
558                 
559                 sdrawline(G.vd->mx-20, G.vd->my, G.vd->mx-5, G.vd->my);
560                 sdrawline(G.vd->mx+5, G.vd->my, G.vd->mx+20, G.vd->my);
561                 sdrawline(G.vd->mx, G.vd->my-20, G.vd->mx, G.vd->my-5);
562                 sdrawline(G.vd->mx, G.vd->my+5, G.vd->mx, G.vd->my+20);
563         }
564 }
565
566 static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
567 {
568         float winmax= MAX2(v3d->area->winx, v3d->area->winy);
569         float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
570
571         if(aspect>1.0) {
572                 size_r[0]= winmax;
573                 size_r[1]= winmax/aspect;
574         } else {
575                 size_r[0]= winmax*aspect;
576                 size_r[1]= winmax;
577         }
578 }
579
580 void calc_viewborder(struct View3D *v3d, rcti *viewborder_r)
581 {
582         float zoomfac, size[2];
583
584         view3d_get_viewborder_size(v3d, size);
585
586                 /* magic zoom calculation, no idea what
587              * it signifies, if you find out, tell me! -zr
588                  */
589         zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
590         zoomfac= (zoomfac*zoomfac)*0.25;
591         
592         size[0]= size[0]*zoomfac;
593         size[1]= size[1]*zoomfac;
594
595                 /* center in window */
596         viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
597         viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
598         viewborder_r->xmax= viewborder_r->xmin + size[0];
599         viewborder_r->ymax= viewborder_r->ymin + size[1];
600 }
601
602 void view3d_set_1_to_1_viewborder(View3D *v3d)
603 {
604         float size[2];
605         int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
606
607         view3d_get_viewborder_size(v3d, size);
608
609         v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
610         v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
611 }
612
613 static void drawviewborder(void)
614 {
615         float fac, a;
616         float x1, x2, y1, y2;
617         float x3, y3, x4, y4;
618         rcti viewborder;
619
620         calc_viewborder(G.vd, &viewborder);
621         x1= viewborder.xmin;
622         y1= viewborder.ymin;
623         x2= viewborder.xmax;
624         y2= viewborder.ymax;
625
626         /* rand */
627         setlinestyle(3);
628         cpack(0);
629         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
630         glRectf(x1+1,  y1-1,  x2+1,  y2-1); 
631         
632         cpack(0xFFFFFF);
633         glRectf(x1,  y1,  x2,  y2); 
634
635         /* border */
636         if(G.scene->r.mode & R_BORDER) {
637                 
638                 cpack(0);
639                 x3= x1+ G.scene->r.border.xmin*(x2-x1);
640                 y3= y1+ G.scene->r.border.ymin*(y2-y1);
641                 x4= x1+ G.scene->r.border.xmax*(x2-x1);
642                 y4= y1+ G.scene->r.border.ymax*(y2-y1);
643                 
644                 glRectf(x3+1,  y3-1,  x4+1,  y4-1); 
645                 
646                 cpack(0x4040FF);
647                 glRectf(x3,  y3,  x4,  y4); 
648         }
649
650         /* safetykader */
651
652         fac= 0.1;
653         
654         a= fac*(x2-x1);
655         x1+= a; 
656         x2-= a;
657
658         a= fac*(y2-y1);
659         y1+= a;
660         y2-= a;
661
662         cpack(0);
663         glRectf(x1+1,  y1-1,  x2+1,  y2-1);
664         cpack(0xFFFFFF);
665         glRectf(x1,  y1,  x2,  y2);
666
667         setlinestyle(0);
668         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
669
670 }
671
672
673 void backdrawview3d(int test)
674 {
675         struct Base *base;
676         int tel=1;
677
678         if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT));
679         else {
680                 G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
681                 return;
682         }
683
684         if(G.vd->flag & V3D_NEEDBACKBUFDRAW); else return;
685         if(G.obedit) {
686                 G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
687                 return;
688         }
689         
690         if(test) {
691                 if(qtest()) {
692                         addafterqueue(curarea->win, BACKBUFDRAW, 1);
693                         return;
694                 }
695         }
696
697         if(G.vd->drawtype > OB_WIRE) G.zbuf= TRUE;
698         curarea->win_swap &= ~WIN_BACK_OK;
699         
700         glDisable(GL_DITHER);
701
702         glClearColor(0.0, 0.0, 0.0, 0.0); 
703         if(G.zbuf) {
704                 glEnable(GL_DEPTH_TEST);
705                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
706         }
707         else {
708                 glClear(GL_COLOR_BUFFER_BIT);
709                 glDisable(GL_DEPTH_TEST);
710         }
711         
712         G.f |= G_BACKBUFSEL;
713         
714         if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
715                 base= (G.scene->basact);
716                 if(base && (base->lay & G.vd->lay)) {
717                         draw_object(base);
718                 }
719         }
720         else {
721
722                 base= (G.scene->base.first);
723                 while(base) {
724                         
725                         /* elke base ivm meerdere windows */
726                         base->selcol= 0x070707 | ( ((tel & 0xF00)<<12) + ((tel & 0xF0)<<8) + ((tel & 0xF)<<4) );
727                         tel++;
728         
729                         if(base->lay & G.vd->lay) {
730                                 
731                                 if(test) {
732                                         if(qtest()) {
733                                                 addafterqueue(curarea->win, BACKBUFDRAW, 1);
734                                                 break;
735                                         }
736                                 }
737                                 
738                                 cpack(base->selcol);
739                                 draw_object(base);
740                         }
741                         base= base->next;
742                 }
743         }
744         
745         if(base==0) G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
746
747         G.f &= ~G_BACKBUFSEL;
748         G.zbuf= FALSE; 
749         glDisable(GL_DEPTH_TEST);
750         glEnable(GL_DITHER);
751 }
752
753                 
754 void drawname(Object *ob)
755 {
756         cpack(0x404040);
757         glRasterPos3f(0.0,  0.0,  0.0);
758         
759         BMF_DrawString(G.font, " ");
760         BMF_DrawString(G.font, ob->id.name+2);
761 }
762
763 static void draw_view_icon(void)
764 {
765         BIFIconID icon;
766         
767         if(G.vd->view==7) icon= ICON_AXIS_TOP;
768         else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
769         else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
770         else return ;
771
772         glEnable(GL_BLEND);
773         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
774         
775         glRasterPos2f(5.0, 5.0);
776         BIF_draw_icon(icon);
777         
778         glBlendFunc(GL_ONE,  GL_ZERO); 
779         glDisable(GL_BLEND);
780 }
781
782 void drawview3d(void)
783 {
784         Base *base;
785         Object *ob;
786         
787         setwinmatrixview3d(0);  /* 0= geen pick rect */
788
789         setviewmatrixview3d();
790
791         Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
792         Mat4Invert(G.vd->persinv, G.vd->persmat);
793         Mat4Invert(G.vd->viewinv, G.vd->viewmat);
794
795         if(G.vd->drawtype > OB_WIRE) {
796                 G.zbuf= TRUE;
797                 glEnable(GL_DEPTH_TEST);
798                 if(G.f & G_SIMULATION) {
799                         glClearColor(0.0, 0.0, 0.0, 0.0); 
800                 }
801                 else {
802                         glClearColor(0.45, 0.45, 0.45, 0.0); 
803                 }
804                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
805                 
806                 glLoadIdentity();
807         }
808         else {
809                 glClearColor(0.45, 0.45, 0.45, 0.0); 
810                 glClear(GL_COLOR_BUFFER_BIT);
811         }
812         
813         myloadmatrix(G.vd->viewmat);
814
815         if(G.vd->view==0 || G.vd->persp!=0) {
816                 drawfloor();
817                 if(G.vd->persp==2) {
818                         if(G.scene->world) {
819                                 if(G.scene->world->mode & WO_STARS) RE_make_stars(star_stuff_init_func,
820                                                                                                                                   star_stuff_vertex_func,
821                                                                                                                                   star_stuff_term_func);
822                         }
823                         if(G.vd->flag & V3D_DISPBGPIC) draw_bgpic();
824                 }
825         }
826         else {
827                 drawgrid();
828
829                 if(G.vd->flag & V3D_DISPBGPIC) {
830                         draw_bgpic();
831                 }
832         }
833         
834         /* Clear the constraint "done" flags */
835         for (base = G.scene->base.first; base; base=base->next){
836                 clear_object_constraint_status(base->object);
837         }
838
839         /* eerst set tekenen */
840         if(G.scene->set) {
841         
842                 /* patchje: kleur blijft constant */ 
843                 G.f |= G_PICKSEL;
844
845                 base= G.scene->set->base.first;
846                 while(base) {
847                         if(G.vd->lay & base->lay) {
848                                 where_is_object(base->object);
849
850                                 cpack(0x404040);
851                                 draw_object(base);
852
853                                 if(base->object->transflag & OB_DUPLI) {
854                                         extern ListBase duplilist;
855                                         Base tbase;
856                                         
857                                         tbase= *base;
858                                         
859                                         tbase.flag= OB_FROMDUPLI;
860                                         make_duplilist(G.scene->set, base->object);
861                                         ob= duplilist.first;
862                                         while(ob) {
863                                                 tbase.object= ob;
864                                                 draw_object(&tbase);
865                                                 ob= ob->id.next;
866                                         }
867                                         free_duplilist();
868                                         
869                                 }
870                         }
871                         base= base->next;
872                 }
873                 
874                 G.f &= ~G_PICKSEL;
875         }
876         
877 /* SILLY CODE!!!! */
878 /* See next silly code... why is the same code
879  * ~ duplicated twice, and then this silly if(FALSE)
880  * in part... wacky! and bad!
881  */
882
883         /* eerst niet selected en dupli's */
884         base= G.scene->base.first;
885         while(base) {
886                 
887                 if(G.vd->lay & base->lay) {
888                         
889                         where_is_object(base->object);
890
891                         if(FALSE && base->object->transflag & OB_DUPLI) {
892                                 extern ListBase duplilist;
893                                 Base tbase;
894
895                                 /* altijd eerst original tekenen vanwege make_displist */
896                                 draw_object(base);
897
898                                 /* patchje: kleur blijft constant */ 
899                                 G.f |= G_PICKSEL;
900                                 cpack(0x404040);
901                                 
902                                 tbase.flag= OB_FROMDUPLI;
903                                 make_duplilist(G.scene, base->object);
904
905                                 ob= duplilist.first;
906                                 while(ob) {
907                                         tbase.object= ob;
908                                         draw_object(&tbase);
909                                         ob= ob->id.next;
910                                 }
911                                 free_duplilist();
912                                 
913                                 G.f &= ~G_PICKSEL;                              
914                         }
915                         else if((base->flag & SELECT)==0) {
916                                 draw_object(base);
917                         }
918                         
919                 }
920                 
921                 base= base->next;
922         }
923         /*  selected */
924         base= G.scene->base.first;
925         while(base) {
926                 
927                 if ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
928                         draw_object(base);
929                 }
930                 
931                 base= base->next;
932         }
933
934 /* SILLY CODE!!!! */
935         /* dupli's, als laatste om zeker te zijn de displisten zijn ok */
936         base= G.scene->base.first;
937         while(base) {
938                 
939                 if(G.vd->lay & base->lay) {
940                         if(base->object->transflag & OB_DUPLI) {
941                                 extern ListBase duplilist;
942                                 Base tbase;
943
944                                 /* patchje: kleur blijft constant */ 
945                                 G.f |= G_PICKSEL;
946                                 cpack(0x404040);
947                                 
948                                 tbase.flag= OB_FROMDUPLI;
949                                 make_duplilist(G.scene, base->object);
950
951                                 ob= duplilist.first;
952                                 while(ob) {
953                                         tbase.object= ob;
954                                         draw_object(&tbase);
955                                         ob= ob->id.next;
956                                 }
957                                 free_duplilist();
958                                 
959                                 G.f &= ~G_PICKSEL;                              
960                         }
961                 }
962                 base= base->next;
963         }
964
965
966         if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
967         
968         persp(0);
969         
970         if(G.vd->persp>1) drawviewborder();
971         drawcursor();
972         draw_view_icon();
973         
974         persp(1);
975
976         curarea->win_swap= WIN_BACK_OK;
977         
978         if(G.zbuf) {
979                 G.zbuf= FALSE;
980                 glDisable(GL_DEPTH_TEST);
981         }
982
983         if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
984                 G.vd->flag |= V3D_NEEDBACKBUFDRAW;
985                 addafterqueue(curarea->win, BACKBUFDRAW, 1);
986         }
987 }
988
989
990         /* Called back by rendering system, icky
991          */
992 void drawview3d_render(struct View3D *v3d)
993 {
994         extern short v3d_windowmode;
995         Base *base;
996         Object *ob;
997
998                 /* XXXXXXXX live and die by the hack */
999         free_all_realtime_images();
1000         mywindow_build_and_set_renderwin();
1001         
1002         v3d_windowmode= 1;
1003         setwinmatrixview3d(0);
1004         v3d_windowmode= 0;
1005         glMatrixMode(GL_PROJECTION);
1006         glLoadMatrixf(R.winmat);
1007         glMatrixMode(GL_MODELVIEW);
1008         
1009         setviewmatrixview3d();
1010         glLoadMatrixf(v3d->viewmat);
1011
1012         Mat4MulMat4(v3d->persmat, v3d->viewmat, R.winmat);
1013         Mat4Invert(v3d->persinv, v3d->persmat);
1014         Mat4Invert(v3d->viewinv, v3d->viewmat);
1015
1016         if(v3d->drawtype > OB_WIRE) {
1017                 G.zbuf= TRUE;
1018                 glEnable(GL_DEPTH_TEST);
1019         }
1020
1021         if (v3d->drawtype==OB_TEXTURE && G.scene->world) {
1022                 glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0); 
1023         } else {
1024                 glClearColor(0.45, 0.45, 0.45, 0.0);
1025         }
1026         
1027         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1028         
1029         glLoadIdentity();
1030         glLoadMatrixf(v3d->viewmat);
1031         
1032         /* abuse! to make sure it doesnt draw the helpstuff */
1033         G.f |= G_SIMULATION;
1034
1035         do_all_ipos();
1036         BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
1037         do_all_keys();
1038         do_all_actions();
1039         do_all_ikas();
1040
1041         test_all_displists();
1042
1043         /* niet erg nette calc_ipo en where_is forceer */
1044         ob= G.main->object.first;
1045         while(ob) {
1046                 ob->ctime= -123.456;
1047                 ob= ob->id.next;
1048         }
1049
1050         /* eerst set tekenen */
1051         if(G.scene->set) {
1052         
1053                 /* patchje: kleur blijft constant */ 
1054                 G.f |= G_PICKSEL;
1055                 
1056                 base= G.scene->set->base.first;
1057                 while(base) {
1058                         if(v3d->lay & base->lay) {
1059                                 if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
1060                                 else {
1061                                         where_is_object(base->object);
1062         
1063                                         cpack(0x404040);
1064                                         draw_object(base);
1065         
1066                                         if(base->object->transflag & OB_DUPLI) {
1067                                                 extern ListBase duplilist;
1068                                                 Base tbase;
1069                                                 
1070                                                 tbase.flag= OB_FROMDUPLI;
1071                                                 make_duplilist(G.scene->set, base->object);
1072                                                 ob= duplilist.first;
1073                                                 while(ob) {
1074                                                         tbase.object= ob;
1075                                                         draw_object(&tbase);
1076                                                         ob= ob->id.next;
1077                                                 }
1078                                                 free_duplilist();
1079                                         }
1080                                 }
1081                         }
1082                         base= base->next;
1083                 }
1084                 
1085                 G.f &= ~G_PICKSEL;
1086         }
1087         for (base = G.scene->base.first; base; base=base->next){
1088                 clear_object_constraint_status(base->object);
1089         }
1090         /* eerst niet selected en dupli's */
1091         base= G.scene->base.first;
1092         while(base) {
1093                 
1094                 if(v3d->lay & base->lay) {
1095                         if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
1096                         else {
1097                                 where_is_object(base->object);
1098         
1099                                 if(base->object->transflag & OB_DUPLI) {
1100                                         extern ListBase duplilist;
1101                                         Base tbase;
1102                                         
1103                                         /* altijd eerst original tekenen vanwege make_displist */
1104                                         draw_object(base);
1105                                         
1106                                         /* patchje: kleur blijft constant */ 
1107                                         G.f |= G_PICKSEL;
1108                                         cpack(0x404040);
1109                                         
1110                                         tbase.flag= OB_FROMDUPLI;
1111                                         make_duplilist(G.scene, base->object);
1112                                         ob= duplilist.first;
1113                                         while(ob) {
1114                                                 tbase.object= ob;
1115                                                 draw_object(&tbase);
1116                                                 ob= ob->id.next;
1117                                         }
1118                                         free_duplilist();
1119                                         
1120                                         G.f &= ~G_PICKSEL;                              
1121                                 }
1122                                 else if((base->flag & SELECT)==0) {
1123                                         draw_object(base);
1124                                 }
1125                         }
1126                 }
1127                 
1128                 base= base->next;
1129         }
1130
1131         /*  selected */
1132         base= G.scene->base.first;
1133         while(base) {
1134                 
1135                 if ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
1136                         if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
1137                         else draw_object(base);
1138                 }
1139                 
1140                 base= base->next;
1141         }
1142
1143         if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
1144         
1145         if(G.zbuf) {
1146                 G.zbuf= FALSE;
1147                 glDisable(GL_DEPTH_TEST);
1148         }
1149         
1150         G.f &= ~G_SIMULATION;
1151
1152         glFinish();
1153
1154         glReadPixels(0, 0, R.rectx, R.recty, GL_RGBA, GL_UNSIGNED_BYTE, R.rectot);
1155         glLoadIdentity();
1156
1157         free_all_realtime_images();
1158 }
1159
1160
1161 double tottime = 0.0;
1162
1163 int update_time(void)
1164 {
1165         static double ltime;
1166         double time;
1167
1168         time = PIL_check_seconds_timer();
1169         
1170         tottime += (time - ltime);
1171         ltime = time;
1172         return (tottime < 0.0);
1173 }
1174
1175 double speed_to_swaptime(int speed)
1176 {
1177         switch(speed) {
1178         case 1:
1179                 return 1.0/60.0;
1180         case 2:
1181                 return 1.0/50.0;
1182         case 3:
1183                 return 1.0/30.0;
1184         case 4:
1185                 return 1.0/25.0;
1186         case 5:
1187                 return 1.0/20.0;
1188         case 6:
1189                 return 1.0/15.0;
1190         case 7:
1191                 return 1.0/12.5;
1192         case 8:
1193                 return 1.0/10.0;
1194         case 9:
1195                 return 1.0/6.0;
1196         }
1197         return 1.0/4.0;
1198 }
1199
1200 double key_to_swaptime(int key)
1201 {
1202         switch(key) {
1203         case PAD1:
1204                 G.animspeed= 1;
1205                 tottime= 0;
1206                 return speed_to_swaptime(1);
1207         case PAD2:
1208                 G.animspeed= 2;
1209                 tottime= 0;
1210                 return speed_to_swaptime(2);
1211         case PAD3:
1212                 G.animspeed= 3;
1213                 tottime= 0;
1214                 return speed_to_swaptime(3);
1215         case PAD4:
1216                 G.animspeed= 4;
1217                 tottime= 0;
1218                 return speed_to_swaptime(4);
1219         case PAD5:
1220                 G.animspeed= 5;
1221                 tottime= 0;
1222                 return speed_to_swaptime(5);
1223         case PAD6:
1224                 G.animspeed= 6;
1225                 tottime= 0;
1226                 return speed_to_swaptime(6);
1227         case PAD7:
1228                 G.animspeed= 7;
1229                 tottime= 0;
1230                 return speed_to_swaptime(7);
1231         case PAD8:
1232                 G.animspeed= 8;
1233                 tottime= 0;
1234                 return speed_to_swaptime(8);
1235         case PAD9:
1236                 G.animspeed= 9;
1237                 tottime= 0;
1238                 return speed_to_swaptime(9);
1239         }
1240         
1241         return speed_to_swaptime(G.animspeed);
1242 }
1243
1244 #ifdef NAN_LINEAR_PHYSICS
1245
1246 void sumo_callback(void *obp)
1247 {
1248         Object *ob= obp;
1249         SM_Vector3 vec;
1250         float matf[3][3];
1251         int i, j;
1252
1253     SM_GetMatrixf(ob->sumohandle, ob->obmat[0]);
1254
1255         VECCOPY(ob->loc, ob->obmat[3]);
1256         
1257     for (i = 0; i < 3; ++i) {
1258         for (j = 0; j < 3; ++j) {
1259             matf[i][j] = ob->obmat[i][j];
1260         }
1261     }
1262     Mat3ToEul(matf, ob->rot);
1263 }
1264
1265 void init_anim_sumo(void)
1266 {
1267         extern Material defmaterial;
1268         Base *base;
1269     Mesh *me;
1270         Object *ob;
1271     Material *mat;
1272         MFace *mface;
1273         MVert *mvert;
1274     float centre[3], size[3];
1275         int a;
1276     SM_ShapeHandle shape;
1277         SM_SceneHandle scene;
1278     SM_Material material;
1279     SM_MassProps massprops;
1280     SM_Vector3 vec;
1281     SM_Vector3 scaling;
1282         
1283         scene= SM_CreateScene();
1284         G.scene->sumohandle = scene;
1285         
1286         vec[0]=  0.0;
1287         vec[1]=  0.0;
1288         vec[2]= -9.8;
1289         SM_SetForceField(scene, vec);
1290         
1291     /* ton: cylinders & cones are still Y-axis up, will be Z-axis later */
1292     /* ton: write location/rotation save and restore */
1293         
1294         base= FIRSTBASE;
1295         while (base) {
1296                 if (G.vd->lay & base->lay) {
1297             ob= base->object;
1298                          
1299             /* define shape, for now only meshes take part in physics */
1300             get_local_bounds(ob, centre, size);
1301             
1302             if (ob->type==OB_MESH) {
1303                 me= ob->data;
1304                 
1305                 if (ob->gameflag & OB_DYNAMIC) {
1306                     if (me->sumohandle)
1307                         shape= me->sumohandle;
1308                     else {
1309                         /* make new handle */
1310                         switch(ob->boundtype) {
1311                         case OB_BOUND_BOX:
1312                             shape= SM_Box(2.0*size[0], 2.0*size[1], 2.0*size[2]);
1313                             break;
1314                         case OB_BOUND_SPHERE:
1315                             shape= SM_Sphere(size[0]);
1316                             break;
1317                         case OB_BOUND_CYLINDER:
1318                             shape= SM_Cylinder(size[0], 2.0*size[2]);
1319                             break;
1320                         case OB_BOUND_CONE:
1321                             shape= SM_Cone(size[0], 2.0*size[2]);
1322                             break;
1323                         }
1324                         
1325                                                 me->sumohandle= shape;
1326                                         }
1327                     /* sumo material properties */
1328                         mat= give_current_material(ob, 0);
1329                         if(mat==NULL)
1330                         mat= &defmaterial;
1331                     
1332                         material.restitution= mat->reflect;
1333                         material.static_friction= mat->friction;
1334                         material.dynamic_friction= mat->friction;
1335                     
1336                         /* sumo mass properties */
1337                         massprops.mass= ob->mass;
1338                         massprops.center[0]= 0.0;
1339                         massprops.center[1]= 0.0;
1340                         massprops.center[2]= 0.0;
1341
1342                         massprops.inertia[0]= 0.5*ob->mass;
1343                         massprops.inertia[1]= 0.5*ob->mass;
1344                         massprops.inertia[2]= 0.5*ob->mass;
1345
1346                         massprops.orientation[0]= 0.0;
1347                         massprops.orientation[1]= 0.0;
1348                         massprops.orientation[2]= 0.0;
1349                         massprops.orientation[3]= 1.0;
1350
1351                         ob->sumohandle = SM_CreateObject(ob, shape, &material, 
1352                                                      &massprops, sumo_callback);
1353                                         SM_AddObject(scene, ob->sumohandle);
1354                                         
1355                     scaling[0] = ob->size[0];
1356                     scaling[1] = ob->size[1];
1357                     scaling[2] = ob->size[2];
1358                                         SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
1359                                         SM_SetScaling(ob->sumohandle, scaling);
1360
1361                                 }
1362                                 else {
1363                                         if(me->sumohandle) shape= me->sumohandle;
1364                                         else {
1365                                                 /* make new handle */
1366                                 shape= SM_NewComplexShape();
1367                                                 
1368                                                 mface= me->mface;
1369                                                 mvert= me->mvert;
1370                                                 for(a=0; a<me->totface; a++,mface++) {
1371                                                         if(mface->v3) {
1372                                                                 SM_Begin();
1373                                                                 SM_Vertex( (mvert+mface->v1)->co[0], (mvert+mface->v1)->co[1], (mvert+mface->v1)->co[2]);
1374                                                                 SM_Vertex( (mvert+mface->v2)->co[0], (mvert+mface->v2)->co[1], (mvert+mface->v2)->co[2]);
1375                                                                 SM_Vertex( (mvert+mface->v3)->co[0], (mvert+mface->v3)->co[1], (mvert+mface->v3)->co[2]);
1376                                                                 if(mface->v4)
1377                                                                         SM_Vertex( (mvert+mface->v4)->co[0], (mvert+mface->v4)->co[1], (mvert+mface->v4)->co[2]);
1378                                                                 SM_End();
1379                                                         }
1380                                                 }
1381                                                 
1382                                                 SM_EndComplexShape();
1383                                                 
1384                                                 me->sumohandle= shape;
1385                                         }
1386                     /* sumo material properties */
1387                         mat= give_current_material(ob, 0);
1388                         if(mat==NULL)
1389                         mat= &defmaterial;
1390                         material.restitution= mat->reflect;
1391                         material.static_friction= mat->friction;
1392                         material.dynamic_friction= mat->friction;
1393
1394                         /* sumo mass properties */
1395                         massprops.mass= ob->mass;
1396                         massprops.center[0]= 0.0;
1397                         massprops.center[1]= 0.0;
1398                         massprops.center[2]= 0.0;
1399
1400                         massprops.inertia[0]= 0.5*ob->mass;
1401                         massprops.inertia[1]= 0.5*ob->mass;
1402                         massprops.inertia[2]= 0.5*ob->mass;
1403
1404                         massprops.orientation[0]= 0.0;
1405                         massprops.orientation[1]= 0.0;
1406                         massprops.orientation[2]= 0.0;
1407                         massprops.orientation[3]= 1.0;
1408
1409                         ob->sumohandle= SM_CreateObject(ob, shape, &material, NULL, NULL);
1410                                         SM_AddObject(scene, ob->sumohandle);
1411
1412                     scaling[0] = ob->size[0];
1413                     scaling[1] = ob->size[1];
1414                     scaling[2] = ob->size[2];
1415                                         SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
1416                                         SM_SetScaling(ob->sumohandle, scaling);
1417                                 }
1418             }
1419         }       
1420         base= base->next;
1421     }
1422 }
1423
1424 /* update animated objects */
1425 void update_anim_sumo(void)
1426 {
1427     SM_Vector3 scaling;
1428
1429         Base *base;
1430         Object *ob;
1431         Mesh *me;
1432         
1433         base= FIRSTBASE;
1434         while(base) {
1435                 if(G.vd->lay & base->lay) {
1436                         ob= base->object;
1437                         
1438                         if(ob->sumohandle) {
1439                                 if((ob->gameflag & OB_DYNAMIC)==0) {
1440                                         /* evt: optimise, check for anim */
1441                     scaling[0] = ob->size[0];
1442                     scaling[1] = ob->size[1];
1443                     scaling[2] = ob->size[2];
1444                                         SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
1445                                         SM_SetScaling(ob->sumohandle, scaling);
1446                                 }
1447                         }                               
1448                 }
1449                 base= base->next;
1450         }
1451
1452 }
1453
1454 void end_anim_sumo(void)
1455 {
1456         Base *base;
1457         Object *ob;
1458         Mesh *me;
1459         
1460         base= FIRSTBASE;
1461         while(base) {
1462                 if(G.vd->lay & base->lay) {
1463                         ob= base->object;
1464                         
1465             if(ob->type==OB_MESH) {
1466                                 if(ob->sumohandle) {
1467                                         SM_RemoveObject(G.scene->sumohandle, ob->sumohandle);
1468                                         SM_DeleteObject(ob->sumohandle);
1469                                         ob->sumohandle= NULL;
1470                                 }
1471                                 me= ob->data;
1472                                 if(me->sumohandle) {
1473                                         SM_DeleteShape(me->sumohandle);
1474                                         me->sumohandle= NULL;
1475                                 }
1476                         }
1477                 }
1478                 base= base->next;
1479         }
1480         if(G.scene->sumohandle) {
1481                 SM_DeleteScene(G.scene->sumohandle);
1482                 G.scene->sumohandle= NULL;
1483         }
1484 }
1485
1486 #endif
1487
1488 void inner_play_anim_loop(int init, int mode)
1489 {
1490         ScrArea *sa;
1491         static ScrArea *oldsa;
1492         static double swaptime;
1493         static int curmode;
1494         
1495         /* init */
1496         if(init) {
1497                 oldsa= curarea;
1498                 swaptime= speed_to_swaptime(G.animspeed);
1499                 tottime= 0.0;
1500                 curmode= mode;
1501 #ifdef NAN_LINEAR_PHYSICS
1502         init_anim_sumo();
1503 #endif        
1504                 return;
1505         }
1506
1507         set_timecursor(CFRA);
1508         do_all_ipos();
1509         BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
1510         do_all_keys();
1511         do_all_actions();
1512         do_all_ikas();
1513
1514
1515         test_all_displists();
1516 #ifdef NAN_LINEAR_PHYSICS       
1517         update_anim_sumo();
1518         
1519         SM_Proceed(G.scene->sumohandle, swaptime, 40, NULL);
1520 #endif
1521         sa= G.curscreen->areabase.first;
1522         while(sa) {
1523                 if(sa==oldsa) {
1524                         scrarea_do_windraw(sa);
1525                 }
1526                 else if(curmode) {
1527                         if ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ) {
1528                                 scrarea_do_windraw(sa);
1529                         }
1530                 }
1531                 
1532                 sa= sa->next;   
1533         }
1534         
1535         /* minimaal swaptime laten voorbijgaan */
1536         tottime -= swaptime;
1537         while (update_time()) PIL_sleep_ms(1);
1538
1539         if(CFRA==EFRA) {
1540                 if (tottime > 0.0) tottime = 0.0;
1541                 CFRA= SFRA;
1542         }
1543         else CFRA++;
1544         
1545 }
1546
1547 int play_anim(int mode)
1548 {
1549         ScrArea *sa, *oldsa;
1550         int cfraont;
1551         unsigned short event=0;
1552         short val;
1553         
1554         /* patch voor zeer oude scenes */
1555         if(SFRA==0) SFRA= 1;
1556         if(EFRA==0) EFRA= 250;
1557         
1558         if(SFRA>EFRA) return 0;
1559         
1560         update_time();
1561
1562         /* waitcursor(1); */
1563         G.f |= G_PLAYANIM;              /* in sequence.c en view.c wordt dit afgevangen */
1564
1565         cfraont= CFRA;
1566         oldsa= curarea;
1567         
1568         inner_play_anim_loop(1, mode);  /* 1==init */
1569
1570         while(TRUE) {
1571
1572                 inner_play_anim_loop(0, 0);
1573         
1574                 screen_swapbuffers();
1575                 
1576                 while(qtest()) {
1577                 
1578                         event= extern_qread(&val);
1579                         if(event==ESCKEY) break;
1580                         else if(event==MIDDLEMOUSE) {
1581                                 if(U.flag & VIEWMOVE) {
1582                                         if(G.qual & LR_SHIFTKEY) viewmove(0);
1583                                         else if(G.qual & LR_CTRLKEY) viewmove(2);
1584                                         else viewmove(1);
1585                                 }
1586                                 else {
1587                                         if(G.qual & LR_SHIFTKEY) viewmove(1);
1588                                         else if(G.qual & LR_CTRLKEY) viewmove(2);
1589                                         else viewmove(0);
1590                                 }
1591                         }
1592                         else if(val) {
1593                                 if(event==PAGEUPKEY) {
1594                                         Group *group= G.main->group.first;
1595                                         while(group) {
1596                                                 next_group_key(group);
1597                                                 group= group->id.next;
1598                                         }
1599                                 }
1600                                 else if(event==PAGEDOWNKEY) {
1601                                         Group *group= G.main->group.first;
1602                                         while(group) {
1603                                                 prev_group_key(group);
1604                                                 group= group->id.next;
1605                                         }
1606                                 }
1607                         }
1608                 }
1609                 if(event==ESCKEY || event==SPACEKEY) break;
1610                                 
1611                 if(mode==2 && CFRA==EFRA) break;        
1612         }
1613
1614         if(event==SPACEKEY);
1615         else CFRA= cfraont;
1616         
1617         do_all_ipos();
1618         do_all_keys();
1619         do_all_actions();
1620         do_all_ikas();
1621
1622
1623         if(oldsa!=curarea) areawinset(oldsa->win);
1624         
1625         /* restore all areas */
1626         sa= G.curscreen->areabase.first;
1627         while(sa) {
1628                 if( (mode && sa->spacetype==SPACE_VIEW3D) || sa==curarea) addqueue(sa->win, REDRAW, 1);
1629                 
1630                 sa= sa->next;   
1631         }
1632         
1633         /* speed button */
1634         allqueue(REDRAWBUTSANIM, 0);
1635         /* groups could have changed ipo */
1636         allspace(REMAKEIPO, 0);
1637         allqueue(REDRAWIPO, 0);
1638         allqueue(REDRAWNLA, 0);
1639         allqueue (REDRAWACTION, 0);
1640         /* vooropig */
1641         update_for_newframe();
1642 #ifdef NAN_LINEAR_PHYSICS       
1643         end_anim_sumo();
1644 #endif
1645         waitcursor(0);
1646         G.f &= ~G_PLAYANIM;
1647         
1648         if (event==ESCKEY || event==SPACEKEY) return 1;
1649         else return 0;
1650 }