Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/drawview.c')
-rw-r--r--source/blender/src/drawview.c1650
1 files changed, 1650 insertions, 0 deletions
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
new file mode 100644
index 00000000000..1db14d8cad9
--- /dev/null
+++ b/source/blender/src/drawview.c
@@ -0,0 +1,1650 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+//#define NAN_LINEAR_PHYSICS
+
+#include <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/times.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_group_types.h"
+#include "DNA_image_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_constraint.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_ika.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_space.h"
+#include "BIF_buttons.h"
+#include "BIF_drawimage.h"
+#include "BIF_editgroup.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_drawmesh.h"
+#include "BDR_drawobject.h"
+
+#include "BSE_view.h"
+#include "BSE_drawview.h"
+#include "BSE_headerbuttons.h"
+
+#include "RE_renderconverter.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+#include "interface.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+/* Modules used */
+#include "render.h"
+#include "radio.h"
+
+/* for physics in animation playback */
+#ifdef NAN_LINEAR_PHYSICS
+#include "sumo.h"
+#endif
+
+/* locals */
+void drawname(Object *ob);
+void star_stuff_init_func(void);
+void star_stuff_vertex_func(float* i);
+void star_stuff_term_func(void);
+
+void star_stuff_init_func(void)
+{
+ cpack(-1);
+ glPointSize(1.0);
+ glBegin(GL_POINTS);
+}
+void star_stuff_vertex_func(float* i)
+{
+ glVertex3fv(i);
+}
+void star_stuff_term_func(void)
+{
+ glEnd();
+}
+
+void setalpha_bgpic(BGpic *bgpic)
+{
+ int x, y, alph;
+ char *rect;
+
+ alph= (int)(255.0*(1.0-bgpic->blend));
+
+ rect= (char *)bgpic->rect;
+ for(y=0; y< bgpic->yim; y++) {
+ for(x= bgpic->xim; x>0; x--, rect+=4) {
+ rect[3]= alph;
+ }
+ }
+}
+
+
+static float light_pos1[] = { -0.3, 0.3, 0.90, 0.0 };
+/* static float light_pos2[] = { 0.3, -0.3, -0.90, 0.0 }; never used? */
+
+void default_gl_light(void)
+{
+ float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ float light_col1[] = { 0.8, 0.8, 0.8, 0.0 };
+
+ int a;
+
+ glLightfv(GL_LIGHT0, GL_POSITION, light_pos1);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_col1);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, mat_specular);
+
+ glEnable(GL_LIGHT0);
+ for(a=1; a<8; a++) glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHTING);
+
+ glDisable(GL_COLOR_MATERIAL);
+}
+
+void init_gl_stuff(void)
+{
+ float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ float mat_shininess[] = { 35.0 };
+/* float one= 1.0; */
+ int a, x, y;
+ GLubyte pat[32*32];
+ const GLubyte *patc= pat;
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+
+ default_gl_light();
+
+ /* no local viewer, looks ugly in ortho mode */
+ /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
+
+ glDepthFunc(GL_LEQUAL);
+ /* scaling matrices */
+ glEnable(GL_NORMALIZE);
+
+ glShadeModel(GL_FLAT);
+
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_LOGIC_OP);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_TEXTURE_1D);
+ glDisable(GL_TEXTURE_2D);
+
+ glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
+ glPixelTransferi(GL_RED_SCALE, 1);
+ glPixelTransferi(GL_RED_BIAS, 0);
+ glPixelTransferi(GL_GREEN_SCALE, 1);
+ glPixelTransferi(GL_GREEN_BIAS, 0);
+ glPixelTransferi(GL_BLUE_SCALE, 1);
+ glPixelTransferi(GL_BLUE_BIAS, 0);
+ glPixelTransferi(GL_ALPHA_SCALE, 1);
+ glPixelTransferi(GL_ALPHA_BIAS, 0);
+
+ a= 0;
+ for(x=0; x<32; x++) {
+ for(y=0; y<4; y++) {
+ if( (x) & 1) pat[a++]= 0x88;
+ else pat[a++]= 0x22;
+ }
+ }
+
+ glPolygonStipple(patc);
+
+
+ init_realtime_GL();
+}
+
+void two_sided(int val)
+{
+
+ /* twosided aan: geft errors bij x flip! */
+ glLightModeliv(GL_LIGHT_MODEL_TWO_SIDE, (GLint *)&val);
+}
+
+void circf(float x, float y, float rad)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ glPushMatrix();
+
+ glTranslatef(x, y, 0.);
+
+ gluDisk( qobj, 0.0, rad, 32, 1);
+
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+void circ(float x, float y, float rad)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+
+ glPushMatrix();
+
+ glTranslatef(x, y, 0.);
+
+ gluDisk( qobj, 0.0, rad, 32, 1);
+
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+/* ********** IN ONTWIKKELING ********** */
+
+static void draw_bgpic(void)
+{
+ BGpic *bgpic;
+ Image *ima;
+ float vec[3], fac, asp, zoomx, zoomy;
+ int x1, y1, x2, y2, cx, cy;
+ short mval[2];
+
+ bgpic= G.vd->bgpic;
+ if(bgpic==0) return;
+
+ if(bgpic->tex) {
+ init_render_texture(bgpic->tex);
+ free_unused_animimages();
+ ima= bgpic->tex->ima;
+ end_render_texture(bgpic->tex);
+ }
+ else {
+ ima= bgpic->ima;
+ }
+
+ if(ima==0) return;
+ if(ima->ok==0) return;
+
+ /* plaatje testen */
+ if(ima->ibuf==0) {
+
+ if(bgpic->rect) MEM_freeN(bgpic->rect);
+ bgpic->rect= 0;
+
+ if(bgpic->tex) {
+ ima_ibuf_is_nul(bgpic->tex);
+ }
+ else {
+ waitcursor(1);
+ load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
+ waitcursor(0);
+ }
+ if(ima->ibuf==0) {
+ ima->ok= 0;
+ return;
+ }
+ }
+
+ if(bgpic->rect==0) {
+
+ bgpic->rect= MEM_dupallocN(ima->ibuf->rect);
+ bgpic->xim= ima->ibuf->x;
+ bgpic->yim= ima->ibuf->y;
+ setalpha_bgpic(bgpic);
+ }
+
+ if(G.vd->persp==2) {
+ rcti vb;
+
+ calc_viewborder(G.vd, &vb);
+
+ x1= vb.xmin;
+ y1= vb.ymin;
+ x2= vb.xmax;
+ y2= vb.ymax;
+ }
+ else {
+ /* windowco berekenen */
+ initgrabz(0.0, 0.0, 0.0);
+ window_to_3d(vec, 1, 0);
+ fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
+ fac= 1.0/fac;
+
+ asp= ( (float)ima->ibuf->y)/(float)ima->ibuf->x;
+
+ vec[0]= vec[1]= vec[2]= 0.0;
+ project_short_noclip(vec, mval);
+ cx= mval[0];
+ cy= mval[1];
+
+ x1= cx+ fac*(bgpic->xof-bgpic->size);
+ y1= cy+ asp*fac*(bgpic->yof-bgpic->size);
+ x2= cx+ fac*(bgpic->xof+bgpic->size);
+ y2= cy+ asp*fac*(bgpic->yof+bgpic->size);
+ }
+
+ /* volledige clip? */
+
+ if(x2 < 0 ) return;
+ if(y2 < 0 ) return;
+ if(x1 > curarea->winx ) return;
+ if(y1 > curarea->winy ) return;
+
+ zoomx= x2-x1;
+ zoomx /= (float)ima->ibuf->x;
+ zoomy= y2-y1;
+ zoomy /= (float)ima->ibuf->y;
+
+ glEnable(GL_BLEND);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ rectwrite_part(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winrct.xmax, curarea->winrct.ymax,
+ x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, ima->ibuf->x, ima->ibuf->y, zoomx, zoomy, bgpic->rect);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+
+}
+
+void timestr(double time, char *str)
+{
+ /* formaat 00:00:00.00 (hr:min:sec) string moet 12 lang */
+ int hr= (int) time/(60*60);
+ int min= (int) fmod(time/60, 60.0);
+ int sec= (int) fmod(time, 60.0);
+ int hun= (int) fmod(time*100.0, 100.0);
+
+ if (hr) {
+ sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
+ } else {
+ sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
+ }
+
+ str[11]=0;
+}
+
+
+static void drawgrid(void)
+{
+ /* extern short bgpicmode; */
+ float wx, wy, x, y, fw, fx, fy, dx;
+ float vec4[4];
+
+ vec4[0]=vec4[1]=vec4[2]=0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+ fx= vec4[0];
+ fy= vec4[1];
+ fw= vec4[3];
+
+ wx= (curarea->winx/2.0); /* ivm afrondfoutjes, grid op verkeerde plek */
+ wy= (curarea->winy/2.0);
+
+ x= (wx)*fx/fw;
+ y= (wy)*fy/fw;
+
+ vec4[0]=vec4[1]=G.vd->grid;
+ vec4[2]= 0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+ fx= vec4[0];
+ fy= vec4[1];
+ fw= vec4[3];
+
+ dx= fabs(x-(wx)*fx/fw);
+ if(dx==0) dx= fabs(y-(wy)*fy/fw);
+
+ if(dx<6.0) {
+ dx*= 10.0;
+ setlinestyle(3);
+ if(dx<6.0) {
+ dx*= 10.0;
+ if(dx<6.0) {
+ setlinestyle(0);
+ return;
+ }
+ }
+ }
+
+ persp(0);
+
+ cpack(0x484848);
+
+ x+= (wx);
+ y+= (wy);
+ fx= x/dx;
+ fx= x-dx*floor(fx);
+
+ while(fx< curarea->winx) {
+ fdrawline(fx, 0.0, fx, (float)curarea->winy);
+ fx+= dx;
+ }
+
+ fy= y/dx;
+ fy= y-dx*floor(fy);
+
+
+ while(fy< curarea->winy) {
+ fdrawline(0.0, fy, (float)curarea->winx, fy);
+ fy+= dx;
+ }
+
+ /* kruis in midden */
+ if(G.vd->view==3) cpack(0xA0D0A0); /* y-as */
+ else cpack(0xA0A0D0); /* x-as */
+
+ fdrawline(0.0, y, (float)curarea->winx, y);
+
+ if(G.vd->view==7) cpack(0xA0D0A0); /* y-as */
+ else cpack(0xE0A0A0); /* z-as */
+
+ fdrawline(x, 0.0, x, (float)curarea->winy);
+
+ persp(1);
+ setlinestyle(0);
+}
+
+
+static void drawfloor(void)
+{
+ View3D *vd;
+ float vert[3], grid;
+ int a, gridlines;
+
+ vd= curarea->spacedata.first;
+
+ vert[2]= 0.0;
+
+ if(vd->gridlines<3) return;
+
+ gridlines= vd->gridlines/2;
+ grid= gridlines*vd->grid;
+
+ cpack(0x484848);
+
+ for(a= -gridlines;a<=gridlines;a++) {
+
+ if(a==0) {
+ if(vd->persp==0) cpack(0xA0D0A0);
+ else cpack(0x402000);
+ }
+ else if(a==1) {
+ cpack(0x484848);
+ }
+
+
+ glBegin(GL_LINE_STRIP);
+ vert[0]= a*vd->grid;
+ vert[1]= grid;
+ glVertex3fv(vert);
+ vert[1]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+
+ cpack(0x484848);
+
+ for(a= -gridlines;a<=gridlines;a++) {
+ if(a==0) {
+ if(vd->persp==0) cpack(0xA0A0D0);
+ else cpack(0);
+ }
+ else if(a==1) {
+ cpack(0x484848);
+ }
+
+ glBegin(GL_LINE_STRIP);
+ vert[1]= a*vd->grid;
+ vert[0]= grid;
+ glVertex3fv(vert );
+ vert[0]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+
+}
+
+static void drawcursor(void)
+{
+
+ if(G.f & G_PLAYANIM) return;
+
+ project_short( give_cursor(), &G.vd->mx);
+
+ G.vd->mxo= G.vd->mx;
+ G.vd->myo= G.vd->my;
+
+ if( G.vd->mx!=3200) {
+
+ setlinestyle(0);
+ cpack(0xFF);
+ circ((float)G.vd->mx, (float)G.vd->my, 10.0);
+ setlinestyle(4);
+ cpack(0xFFFFFF);
+ circ((float)G.vd->mx, (float)G.vd->my, 10.0);
+ setlinestyle(0);
+ cpack(0x0);
+
+ sdrawline(G.vd->mx-20, G.vd->my, G.vd->mx-5, G.vd->my);
+ sdrawline(G.vd->mx+5, G.vd->my, G.vd->mx+20, G.vd->my);
+ sdrawline(G.vd->mx, G.vd->my-20, G.vd->mx, G.vd->my-5);
+ sdrawline(G.vd->mx, G.vd->my+5, G.vd->mx, G.vd->my+20);
+ }
+}
+
+static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
+{
+ float winmax= MAX2(v3d->area->winx, v3d->area->winy);
+ float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
+
+ if(aspect>1.0) {
+ size_r[0]= winmax;
+ size_r[1]= winmax/aspect;
+ } else {
+ size_r[0]= winmax*aspect;
+ size_r[1]= winmax;
+ }
+}
+
+void calc_viewborder(struct View3D *v3d, rcti *viewborder_r)
+{
+ float zoomfac, size[2];
+
+ view3d_get_viewborder_size(v3d, size);
+
+ /* magic zoom calculation, no idea what
+ * it signifies, if you find out, tell me! -zr
+ */
+ zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
+ zoomfac= (zoomfac*zoomfac)*0.25;
+
+ size[0]= size[0]*zoomfac;
+ size[1]= size[1]*zoomfac;
+
+ /* center in window */
+ viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
+ viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
+ viewborder_r->xmax= viewborder_r->xmin + size[0];
+ viewborder_r->ymax= viewborder_r->ymin + size[1];
+}
+
+void view3d_set_1_to_1_viewborder(View3D *v3d)
+{
+ float size[2];
+ int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
+
+ view3d_get_viewborder_size(v3d, size);
+
+ v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
+ v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
+}
+
+static void drawviewborder(void)
+{
+ float fac, a;
+ float x1, x2, y1, y2;
+ float x3, y3, x4, y4;
+ rcti viewborder;
+
+ calc_viewborder(G.vd, &viewborder);
+ x1= viewborder.xmin;
+ y1= viewborder.ymin;
+ x2= viewborder.xmax;
+ y2= viewborder.ymax;
+
+ /* rand */
+ setlinestyle(3);
+ cpack(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glRectf(x1+1, y1-1, x2+1, y2-1);
+
+ cpack(0xFFFFFF);
+ glRectf(x1, y1, x2, y2);
+
+ /* border */
+ if(G.scene->r.mode & R_BORDER) {
+
+ cpack(0);
+ x3= x1+ G.scene->r.border.xmin*(x2-x1);
+ y3= y1+ G.scene->r.border.ymin*(y2-y1);
+ x4= x1+ G.scene->r.border.xmax*(x2-x1);
+ y4= y1+ G.scene->r.border.ymax*(y2-y1);
+
+ glRectf(x3+1, y3-1, x4+1, y4-1);
+
+ cpack(0x4040FF);
+ glRectf(x3, y3, x4, y4);
+ }
+
+ /* safetykader */
+
+ fac= 0.1;
+
+ a= fac*(x2-x1);
+ x1+= a;
+ x2-= a;
+
+ a= fac*(y2-y1);
+ y1+= a;
+ y2-= a;
+
+ cpack(0);
+ glRectf(x1+1, y1-1, x2+1, y2-1);
+ cpack(0xFFFFFF);
+ glRectf(x1, y1, x2, y2);
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+}
+
+
+void backdrawview3d(int test)
+{
+ struct Base *base;
+ int tel=1;
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT));
+ else {
+ G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+ return;
+ }
+
+ if(G.vd->flag & V3D_NEEDBACKBUFDRAW); else return;
+ if(G.obedit) {
+ G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+ return;
+ }
+
+ if(test) {
+ if(qtest()) {
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ return;
+ }
+ }
+
+ if(G.vd->drawtype > OB_WIRE) G.zbuf= TRUE;
+ curarea->win_swap &= ~WIN_BACK_OK;
+
+ glDisable(GL_DITHER);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ if(G.zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ G.f |= G_BACKBUFSEL;
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+ base= (G.scene->basact);
+ if(base && (base->lay & G.vd->lay)) {
+ draw_object(base);
+ }
+ }
+ else {
+
+ base= (G.scene->base.first);
+ while(base) {
+
+ /* elke base ivm meerdere windows */
+ base->selcol= 0x070707 | ( ((tel & 0xF00)<<12) + ((tel & 0xF0)<<8) + ((tel & 0xF)<<4) );
+ tel++;
+
+ if(base->lay & G.vd->lay) {
+
+ if(test) {
+ if(qtest()) {
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ break;
+ }
+ }
+
+ cpack(base->selcol);
+ draw_object(base);
+ }
+ base= base->next;
+ }
+ }
+
+ if(base==0) G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+
+ G.f &= ~G_BACKBUFSEL;
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+}
+
+
+void drawname(Object *ob)
+{
+ cpack(0x404040);
+ glRasterPos3f(0.0, 0.0, 0.0);
+
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, ob->id.name+2);
+}
+
+static void draw_view_icon(void)
+{
+ BIFIconID icon;
+
+ if(G.vd->view==7) icon= ICON_AXIS_TOP;
+ else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
+ else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
+ else return ;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glRasterPos2f(5.0, 5.0);
+ BIF_draw_icon(icon);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+}
+
+void drawview3d(void)
+{
+ Base *base;
+ Object *ob;
+
+ setwinmatrixview3d(0); /* 0= geen pick rect */
+
+ setviewmatrixview3d();
+
+ Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
+ Mat4Invert(G.vd->persinv, G.vd->persmat);
+ Mat4Invert(G.vd->viewinv, G.vd->viewmat);
+
+ if(G.vd->drawtype > OB_WIRE) {
+ G.zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ if(G.f & G_SIMULATION) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ }
+ else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ }
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ }
+ else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ myloadmatrix(G.vd->viewmat);
+
+ if(G.vd->view==0 || G.vd->persp!=0) {
+ drawfloor();
+ if(G.vd->persp==2) {
+ if(G.scene->world) {
+ if(G.scene->world->mode & WO_STARS) RE_make_stars(star_stuff_init_func,
+ star_stuff_vertex_func,
+ star_stuff_term_func);
+ }
+ if(G.vd->flag & V3D_DISPBGPIC) draw_bgpic();
+ }
+ }
+ else {
+ drawgrid();
+
+ if(G.vd->flag & V3D_DISPBGPIC) {
+ draw_bgpic();
+ }
+ }
+
+ /* Clear the constraint "done" flags */
+ for (base = G.scene->base.first; base; base=base->next){
+ clear_object_constraint_status(base->object);
+ }
+
+ /* eerst set tekenen */
+ if(G.scene->set) {
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+
+ base= G.scene->set->base.first;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ where_is_object(base->object);
+
+ cpack(0x404040);
+ draw_object(base);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ tbase= *base;
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene->set, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ }
+ }
+ base= base->next;
+ }
+
+ G.f &= ~G_PICKSEL;
+ }
+
+/* SILLY CODE!!!! */
+/* See next silly code... why is the same code
+ * ~ duplicated twice, and then this silly if(FALSE)
+ * in part... wacky! and bad!
+ */
+
+ /* eerst niet selected en dupli's */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(G.vd->lay & base->lay) {
+
+ where_is_object(base->object);
+
+ if(FALSE && base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* altijd eerst original tekenen vanwege make_displist */
+ draw_object(base);
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ else if((base->flag & SELECT)==0) {
+ draw_object(base);
+ }
+
+ }
+
+ base= base->next;
+ }
+ /* selected */
+ base= G.scene->base.first;
+ while(base) {
+
+ if ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ draw_object(base);
+ }
+
+ base= base->next;
+ }
+
+/* SILLY CODE!!!! */
+ /* dupli's, als laatste om zeker te zijn de displisten zijn ok */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(G.vd->lay & base->lay) {
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ }
+ base= base->next;
+ }
+
+
+ if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
+
+ persp(0);
+
+ if(G.vd->persp>1) drawviewborder();
+ drawcursor();
+ draw_view_icon();
+
+ persp(1);
+
+ curarea->win_swap= WIN_BACK_OK;
+
+ if(G.zbuf) {
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+ G.vd->flag |= V3D_NEEDBACKBUFDRAW;
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ }
+}
+
+
+ /* Called back by rendering system, icky
+ */
+void drawview3d_render(struct View3D *v3d)
+{
+ extern short v3d_windowmode;
+ Base *base;
+ Object *ob;
+
+ /* XXXXXXXX live and die by the hack */
+ free_all_realtime_images();
+ mywindow_build_and_set_renderwin();
+
+ v3d_windowmode= 1;
+ setwinmatrixview3d(0);
+ v3d_windowmode= 0;
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(R.winmat);
+ glMatrixMode(GL_MODELVIEW);
+
+ setviewmatrixview3d();
+ glLoadMatrixf(v3d->viewmat);
+
+ Mat4MulMat4(v3d->persmat, v3d->viewmat, R.winmat);
+ Mat4Invert(v3d->persinv, v3d->persmat);
+ Mat4Invert(v3d->viewinv, v3d->viewmat);
+
+ if(v3d->drawtype > OB_WIRE) {
+ G.zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ if (v3d->drawtype==OB_TEXTURE && G.scene->world) {
+ glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0);
+ } else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ glLoadMatrixf(v3d->viewmat);
+
+ /* abuse! to make sure it doesnt draw the helpstuff */
+ G.f |= G_SIMULATION;
+
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+ test_all_displists();
+
+ /* niet erg nette calc_ipo en where_is forceer */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->ctime= -123.456;
+ ob= ob->id.next;
+ }
+
+ /* eerst set tekenen */
+ if(G.scene->set) {
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+
+ base= G.scene->set->base.first;
+ while(base) {
+ if(v3d->lay & base->lay) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else {
+ where_is_object(base->object);
+
+ cpack(0x404040);
+ draw_object(base);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene->set, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ G.f &= ~G_PICKSEL;
+ }
+ for (base = G.scene->base.first; base; base=base->next){
+ clear_object_constraint_status(base->object);
+ }
+ /* eerst niet selected en dupli's */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(v3d->lay & base->lay) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else {
+ where_is_object(base->object);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* altijd eerst original tekenen vanwege make_displist */
+ draw_object(base);
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ else if((base->flag & SELECT)==0) {
+ draw_object(base);
+ }
+ }
+ }
+
+ base= base->next;
+ }
+
+ /* selected */
+ base= G.scene->base.first;
+ while(base) {
+
+ if ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else draw_object(base);
+ }
+
+ base= base->next;
+ }
+
+ if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
+
+ if(G.zbuf) {
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ G.f &= ~G_SIMULATION;
+
+ glFinish();
+
+ glReadPixels(0, 0, R.rectx, R.recty, GL_RGBA, GL_UNSIGNED_BYTE, R.rectot);
+ glLoadIdentity();
+
+ free_all_realtime_images();
+}
+
+
+double tottime = 0.0;
+
+int update_time(void)
+{
+ static double ltime;
+ double time;
+
+ time = PIL_check_seconds_timer();
+
+ tottime += (time - ltime);
+ ltime = time;
+ return (tottime < 0.0);
+}
+
+double speed_to_swaptime(int speed)
+{
+ switch(speed) {
+ case 1:
+ return 1.0/60.0;
+ case 2:
+ return 1.0/50.0;
+ case 3:
+ return 1.0/30.0;
+ case 4:
+ return 1.0/25.0;
+ case 5:
+ return 1.0/20.0;
+ case 6:
+ return 1.0/15.0;
+ case 7:
+ return 1.0/12.5;
+ case 8:
+ return 1.0/10.0;
+ case 9:
+ return 1.0/6.0;
+ }
+ return 1.0/4.0;
+}
+
+double key_to_swaptime(int key)
+{
+ switch(key) {
+ case PAD1:
+ G.animspeed= 1;
+ tottime= 0;
+ return speed_to_swaptime(1);
+ case PAD2:
+ G.animspeed= 2;
+ tottime= 0;
+ return speed_to_swaptime(2);
+ case PAD3:
+ G.animspeed= 3;
+ tottime= 0;
+ return speed_to_swaptime(3);
+ case PAD4:
+ G.animspeed= 4;
+ tottime= 0;
+ return speed_to_swaptime(4);
+ case PAD5:
+ G.animspeed= 5;
+ tottime= 0;
+ return speed_to_swaptime(5);
+ case PAD6:
+ G.animspeed= 6;
+ tottime= 0;
+ return speed_to_swaptime(6);
+ case PAD7:
+ G.animspeed= 7;
+ tottime= 0;
+ return speed_to_swaptime(7);
+ case PAD8:
+ G.animspeed= 8;
+ tottime= 0;
+ return speed_to_swaptime(8);
+ case PAD9:
+ G.animspeed= 9;
+ tottime= 0;
+ return speed_to_swaptime(9);
+ }
+
+ return speed_to_swaptime(G.animspeed);
+}
+
+#ifdef NAN_LINEAR_PHYSICS
+
+void sumo_callback(void *obp)
+{
+ Object *ob= obp;
+ SM_Vector3 vec;
+ float matf[3][3];
+ int i, j;
+
+ SM_GetMatrixf(ob->sumohandle, ob->obmat[0]);
+
+ VECCOPY(ob->loc, ob->obmat[3]);
+
+ for (i = 0; i < 3; ++i) {
+ for (j = 0; j < 3; ++j) {
+ matf[i][j] = ob->obmat[i][j];
+ }
+ }
+ Mat3ToEul(matf, ob->rot);
+}
+
+void init_anim_sumo(void)
+{
+ extern Material defmaterial;
+ Base *base;
+ Mesh *me;
+ Object *ob;
+ Material *mat;
+ MFace *mface;
+ MVert *mvert;
+ float centre[3], size[3];
+ int a;
+ SM_ShapeHandle shape;
+ SM_SceneHandle scene;
+ SM_Material material;
+ SM_MassProps massprops;
+ SM_Vector3 vec;
+ SM_Vector3 scaling;
+
+ scene= SM_CreateScene();
+ G.scene->sumohandle = scene;
+
+ vec[0]= 0.0;
+ vec[1]= 0.0;
+ vec[2]= -9.8;
+ SM_SetForceField(scene, vec);
+
+ /* ton: cylinders & cones are still Y-axis up, will be Z-axis later */
+ /* ton: write location/rotation save and restore */
+
+ base= FIRSTBASE;
+ while (base) {
+ if (G.vd->lay & base->lay) {
+ ob= base->object;
+
+ /* define shape, for now only meshes take part in physics */
+ get_local_bounds(ob, centre, size);
+
+ if (ob->type==OB_MESH) {
+ me= ob->data;
+
+ if (ob->gameflag & OB_DYNAMIC) {
+ if (me->sumohandle)
+ shape= me->sumohandle;
+ else {
+ /* make new handle */
+ switch(ob->boundtype) {
+ case OB_BOUND_BOX:
+ shape= SM_Box(2.0*size[0], 2.0*size[1], 2.0*size[2]);
+ break;
+ case OB_BOUND_SPHERE:
+ shape= SM_Sphere(size[0]);
+ break;
+ case OB_BOUND_CYLINDER:
+ shape= SM_Cylinder(size[0], 2.0*size[2]);
+ break;
+ case OB_BOUND_CONE:
+ shape= SM_Cone(size[0], 2.0*size[2]);
+ break;
+ }
+
+ me->sumohandle= shape;
+ }
+ /* sumo material properties */
+ mat= give_current_material(ob, 0);
+ if(mat==NULL)
+ mat= &defmaterial;
+
+ material.restitution= mat->reflect;
+ material.static_friction= mat->friction;
+ material.dynamic_friction= mat->friction;
+
+ /* sumo mass properties */
+ massprops.mass= ob->mass;
+ massprops.center[0]= 0.0;
+ massprops.center[1]= 0.0;
+ massprops.center[2]= 0.0;
+
+ massprops.inertia[0]= 0.5*ob->mass;
+ massprops.inertia[1]= 0.5*ob->mass;
+ massprops.inertia[2]= 0.5*ob->mass;
+
+ massprops.orientation[0]= 0.0;
+ massprops.orientation[1]= 0.0;
+ massprops.orientation[2]= 0.0;
+ massprops.orientation[3]= 1.0;
+
+ ob->sumohandle = SM_CreateObject(ob, shape, &material,
+ &massprops, sumo_callback);
+ SM_AddObject(scene, ob->sumohandle);
+
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+
+ }
+ else {
+ if(me->sumohandle) shape= me->sumohandle;
+ else {
+ /* make new handle */
+ shape= SM_NewComplexShape();
+
+ mface= me->mface;
+ mvert= me->mvert;
+ for(a=0; a<me->totface; a++,mface++) {
+ if(mface->v3) {
+ SM_Begin();
+ SM_Vertex( (mvert+mface->v1)->co[0], (mvert+mface->v1)->co[1], (mvert+mface->v1)->co[2]);
+ SM_Vertex( (mvert+mface->v2)->co[0], (mvert+mface->v2)->co[1], (mvert+mface->v2)->co[2]);
+ SM_Vertex( (mvert+mface->v3)->co[0], (mvert+mface->v3)->co[1], (mvert+mface->v3)->co[2]);
+ if(mface->v4)
+ SM_Vertex( (mvert+mface->v4)->co[0], (mvert+mface->v4)->co[1], (mvert+mface->v4)->co[2]);
+ SM_End();
+ }
+ }
+
+ SM_EndComplexShape();
+
+ me->sumohandle= shape;
+ }
+ /* sumo material properties */
+ mat= give_current_material(ob, 0);
+ if(mat==NULL)
+ mat= &defmaterial;
+ material.restitution= mat->reflect;
+ material.static_friction= mat->friction;
+ material.dynamic_friction= mat->friction;
+
+ /* sumo mass properties */
+ massprops.mass= ob->mass;
+ massprops.center[0]= 0.0;
+ massprops.center[1]= 0.0;
+ massprops.center[2]= 0.0;
+
+ massprops.inertia[0]= 0.5*ob->mass;
+ massprops.inertia[1]= 0.5*ob->mass;
+ massprops.inertia[2]= 0.5*ob->mass;
+
+ massprops.orientation[0]= 0.0;
+ massprops.orientation[1]= 0.0;
+ massprops.orientation[2]= 0.0;
+ massprops.orientation[3]= 1.0;
+
+ ob->sumohandle= SM_CreateObject(ob, shape, &material, NULL, NULL);
+ SM_AddObject(scene, ob->sumohandle);
+
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+ }
+ }
+ }
+ base= base->next;
+ }
+}
+
+/* update animated objects */
+void update_anim_sumo(void)
+{
+ SM_Vector3 scaling;
+
+ Base *base;
+ Object *ob;
+ Mesh *me;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ ob= base->object;
+
+ if(ob->sumohandle) {
+ if((ob->gameflag & OB_DYNAMIC)==0) {
+ /* evt: optimise, check for anim */
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+ }
+ }
+ }
+ base= base->next;
+ }
+
+}
+
+void end_anim_sumo(void)
+{
+ Base *base;
+ Object *ob;
+ Mesh *me;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ ob= base->object;
+
+ if(ob->type==OB_MESH) {
+ if(ob->sumohandle) {
+ SM_RemoveObject(G.scene->sumohandle, ob->sumohandle);
+ SM_DeleteObject(ob->sumohandle);
+ ob->sumohandle= NULL;
+ }
+ me= ob->data;
+ if(me->sumohandle) {
+ SM_DeleteShape(me->sumohandle);
+ me->sumohandle= NULL;
+ }
+ }
+ }
+ base= base->next;
+ }
+ if(G.scene->sumohandle) {
+ SM_DeleteScene(G.scene->sumohandle);
+ G.scene->sumohandle= NULL;
+ }
+}
+
+#endif
+
+void inner_play_anim_loop(int init, int mode)
+{
+ ScrArea *sa;
+ static ScrArea *oldsa;
+ static double swaptime;
+ static int curmode;
+
+ /* init */
+ if(init) {
+ oldsa= curarea;
+ swaptime= speed_to_swaptime(G.animspeed);
+ tottime= 0.0;
+ curmode= mode;
+#ifdef NAN_LINEAR_PHYSICS
+ init_anim_sumo();
+#endif
+ return;
+ }
+
+ set_timecursor(CFRA);
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+
+ test_all_displists();
+#ifdef NAN_LINEAR_PHYSICS
+ update_anim_sumo();
+
+ SM_Proceed(G.scene->sumohandle, swaptime, 40, NULL);
+#endif
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa==oldsa) {
+ scrarea_do_windraw(sa);
+ }
+ else if(curmode) {
+ if ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ) {
+ scrarea_do_windraw(sa);
+ }
+ }
+
+ sa= sa->next;
+ }
+
+ /* minimaal swaptime laten voorbijgaan */
+ tottime -= swaptime;
+ while (update_time()) PIL_sleep_ms(1);
+
+ if(CFRA==EFRA) {
+ if (tottime > 0.0) tottime = 0.0;
+ CFRA= SFRA;
+ }
+ else CFRA++;
+
+}
+
+int play_anim(int mode)
+{
+ ScrArea *sa, *oldsa;
+ int cfraont;
+ unsigned short event=0;
+ short val;
+
+ /* patch voor zeer oude scenes */
+ if(SFRA==0) SFRA= 1;
+ if(EFRA==0) EFRA= 250;
+
+ if(SFRA>EFRA) return 0;
+
+ update_time();
+
+ /* waitcursor(1); */
+ G.f |= G_PLAYANIM; /* in sequence.c en view.c wordt dit afgevangen */
+
+ cfraont= CFRA;
+ oldsa= curarea;
+
+ inner_play_anim_loop(1, mode); /* 1==init */
+
+ while(TRUE) {
+
+ inner_play_anim_loop(0, 0);
+
+ screen_swapbuffers();
+
+ while(qtest()) {
+
+ event= extern_qread(&val);
+ if(event==ESCKEY) break;
+ else if(event==MIDDLEMOUSE) {
+ if(U.flag & VIEWMOVE) {
+ if(G.qual & LR_SHIFTKEY) viewmove(0);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(1);
+ }
+ else {
+ if(G.qual & LR_SHIFTKEY) viewmove(1);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(0);
+ }
+ }
+ else if(val) {
+ if(event==PAGEUPKEY) {
+ Group *group= G.main->group.first;
+ while(group) {
+ next_group_key(group);
+ group= group->id.next;
+ }
+ }
+ else if(event==PAGEDOWNKEY) {
+ Group *group= G.main->group.first;
+ while(group) {
+ prev_group_key(group);
+ group= group->id.next;
+ }
+ }
+ }
+ }
+ if(event==ESCKEY || event==SPACEKEY) break;
+
+ if(mode==2 && CFRA==EFRA) break;
+ }
+
+ if(event==SPACEKEY);
+ else CFRA= cfraont;
+
+ do_all_ipos();
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+
+ if(oldsa!=curarea) areawinset(oldsa->win);
+
+ /* restore all areas */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if( (mode && sa->spacetype==SPACE_VIEW3D) || sa==curarea) addqueue(sa->win, REDRAW, 1);
+
+ sa= sa->next;
+ }
+
+ /* speed button */
+ allqueue(REDRAWBUTSANIM, 0);
+ /* groups could have changed ipo */
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ /* vooropig */
+ update_for_newframe();
+#ifdef NAN_LINEAR_PHYSICS
+ end_anim_sumo();
+#endif
+ waitcursor(0);
+ G.f &= ~G_PLAYANIM;
+
+ if (event==ESCKEY || event==SPACEKEY) return 1;
+ else return 0;
+}