/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 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 ***** */ /* screen.c dec/jan 93/94 GRAPHICS * * * * * * Version: $Id: screen.c,v 1.24 2000/09/13 11:52:30 ton Exp $ */ #include "blender.h" #include "graphics.h" #include "render.h" #include "sound.h" #include "interface.h" #ifdef __sgi #include #endif /* TIPS: * * - LET OP DE EDGES, VERTICES ERVAN MOETEN IN VOLGORDE (laagste pointer eerst). Anders onvoorspelbare effecten! * - probleem: flags zijn nog niet echt netjes. Altijd na gebruik op nul zetten. */ /* ********* Globals *********** */ extern bWindow *swinarray[]; /* mywindow.c */ ScrArea *curarea= 0; ScrEdge *curedge= 0; unsigned short fullscreen=1; unsigned short borderless=1; int displaysizex= 0, displaysizey= 0; int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0; short scrmousex, scrmousey; /* worden gezet door mousecallback */ short mainwin=0, winqueue_break= 0, cursonedge=0, visible=1, dodrawscreen= 0; static short mainqueue[MAXQUEUE]; ScrArea *areawinar[MAXWIN]; /* uint edcol[EDGEWIDTH]= {0x0, 0x303030, 0x606060, 0x808080, 0x909090, 0xF0F0F0, 0x0}; */ uint edcol[EDGEWIDTH]= {0x0, 0x505050, 0x909090, 0xF0F0F0, 0x0}; int autosavetime; /* ********* Funkties *********** */ void getdisplaysize(); bScreen *default_foursplit(), *default_twosplit(); ScrEdge *findscredge(ScrVert *v1, ScrVert *v2); void setscreen(bScreen *sc); void drawscreen(); void initscreen(); void moveareas(); void scrollheader(); void testareas(); void area_fullscreen(); void addqueue(short win, ushort event, short val); void editsplitpoint(); void splitarea(ScrArea *sa, char dir, float fac); void joinarea(ScrArea *sa); void select_connected_scredge(bScreen *sc, ScrEdge *curedge); static ushort hor_ptr_bits[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x1008, 0x1818, 0x1c38, 0xffff, 0xffff, 0x1c38, 0x1818, 0x1008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x381c, 0x3c3c, 0x3e7c, 0xffff, 0xffff, 0xffff, 0xffff, 0x3e7c, 0x3c3c, 0x381c, 0x0000, 0x0000, 0x0000, }; static ushort vert_ptr_bits[] = { 0x0180, 0x0180, 0x0180, 0x0ff0, 0x07e0, 0x03c0, 0x0180, 0x0, 0x0, 0x0180, 0x03c0, 0x07e0, 0x0ff0, 0x0180, 0x0180, 0x0180, 0x03c0, 0x03c0, 0x1ff8, 0x1ff8, 0x1ff8, 0x0ff0, 0x07e0, 0x03c0, 0x03c0, 0x07e0, 0x0ff0, 0x1ff8, 0x1ff8, 0x1ff8, 0x03c0, 0x03c0, }; static ushort win_ptr_bits[] = { 0x0000, 0x0180, 0x0180, 0x0180, 0x0000, 0x89b3, 0xfdb3, 0xfdb7, 0xb5bf, 0xb5bb, 0x85b3, 0x0000, 0x0180, 0x0180, 0x0180, 0x0000, 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x03c0, 0x03c0, 0x03c0, 0x03c0 }; void init_screen_cursors() { } void waitcursor(int val) { ScrArea *sa; int oldwin; if(G.curscreen==0) return; if(G.background) return; if(val) { /* only once: for time-cursor */ if(R.flag & R_RENDERING) return; if(R.win && R.win==G.curscreen->winakt) { oldwin= G.curscreen->winakt; mywinset(G.curscreen->mainwin); glutSetCursor(CURSOR_WAIT); mywinset(oldwin); } else glutSetCursor(CURSOR_WAIT); } else if(G.curscreen->winakt>3) { if(R.flag & R_RENDERING) return; sa= areawinar[G.curscreen->winakt]; if(sa->cursor && sa->win==G.curscreen->winakt) glutSetCursor(sa->cursor); else glutSetCursor(CURSOR_STD); } else glutSetCursor(CURSOR_STD); } void tempcursor(int curs) { ScrArea *sa; if(G.curscreen==0) return; if(curs!=CURSOR_STD) glutSetCursor(curs); else if(G.curscreen->winakt) { sa= areawinar[G.curscreen->winakt]; if(sa->win==G.curscreen->winakt) glutSetCursor(sa->cursor); else glutSetCursor(CURSOR_STD); } } void wich_cursor(ScrArea *sa) { /* o.a. als nieuwe space gemaakt */ sa->cursor= CURSOR_STD; if(sa->spacetype==SPACE_VIEW3D) { if(G.obedit) sa->cursor= CURSOR_EDIT; else if(G.f & G_VERTEXPAINT) sa->cursor= CURSOR_VPAINT; else if(G.f & G_FACESELECT) sa->cursor= CURSOR_FACESEL; } if(sa->win==G.curscreen->winakt) glutSetCursor(sa->cursor); } void setcursor_space(int spacetype, short cur) { bScreen *sc; ScrArea *sa; int oldwin; sc= G.main->screen.first; while(sc) { sa= sc->areabase.first; while(sa) { if(sa->spacetype==spacetype) { sa->cursor= cur; if(cur==0) wich_cursor(sa); /* extra test, bv nodig bij verlaten editmode in vertexpaint */ if(sc==G.curscreen && sc->winakt==sa->win) glutSetCursor(sa->cursor); } sa= sa->next; } sc= sc->id.next; } } /* ********* IN/OUT ************* */ void getmouseco_sc(short *mval) /* screen coordinaten */ { if(G.curscreen==0) return; getmouse(mval); /* display coordinaten */ mval[0]-= G.curscreen->startx; mval[1]-= G.curscreen->starty; } void getmouseco_areawin(short *mval) /* interne area coordinaten */ { getmouseco_sc(mval); if(curarea->win) { mval[0]-= curarea->winrct.xmin; mval[1]-= curarea->winrct.ymin; } } void getmouseco_headwin(short *mval) /* interne area coordinaten */ { getmouseco_sc(mval); if(curarea->headwin) { mval[0]-= curarea->headrct.xmin; mval[1]-= curarea->headrct.ymin; } } /* ******** WINDOW & QUEUE ********* */ static short *mainq= mainqueue; ushort qread(short *val) { if( (long)mainq > (long)mainqueue) { mainq-= 2; *val= mainq[1]; return ((ushort *)mainq)[0]; } return 0; } void qenter(ushort event, short val) { int size; short *end; /* avoid non-events: qtest()! */ if(event) { end= mainqueue+MAXQUEUE-2; if( (long)mainq < (long)end) { size= ((long)mainq)-((long)mainqueue); if(size) memmove( mainqueue+2, mainqueue, size); ( (ushort *)mainqueue)[0]= event; mainqueue[1]= val; mainq+= 2; } } } ushort myqtest() { ScrArea *sa; if(mainq != mainqueue) return ((ushort *)mainq)[-2];; return 0; } ushort qtest() { ushort event; #if !defined __BeOS && !defined WIN32 extern Display *__glutDisplay; /* combinatie: deze werkt als oude qtest(). wel daarna screen_qread aanroepen */ if(event=myqtest()) return event; return (XPending(__glutDisplay)); #else if(event=myqtest()) return event; return glutqtest(); #endif } void qreset() { mainq= mainqueue; } short isqueued( short dev ) { return 0; } /* *********** AUTOSAVE ************** */ void reset_autosave() { autosavetime= 0; } void start_autosave(int val) { /* opniew aanzetten */ glutTimerFunc(60000, start_autosave, 0); if(U.flag & AUTOSAVE) { autosavetime++; if(autosavetime >= U.savetime) { qenter(TIMER0, 1); } } else autosavetime= 0; } void set_cursonedge(short mx, short my) { ScrEdge *se, *se1=0, *se2=0, *se3=0, *se4=0; float dist, mindist= 100.0, vec1[2], vec2[2], vec3[2], PdistVL2Dfl(); vec1[0]= mx; vec1[1]= my; curedge= 0; /* als de edge element is van curarea: extra voordeel. Dit voor juiste split en join */ if(curarea) { se1= findscredge(curarea->v1, curarea->v2); se2= findscredge(curarea->v2, curarea->v3); se3= findscredge(curarea->v3, curarea->v4); se4= findscredge(curarea->v4, curarea->v1); } se= G.curscreen->edgebase.first; while(se) { vec2[0]= se->v1->vec.x; vec2[1]= se->v1->vec.y; vec3[0]= se->v2->vec.x; vec3[1]= se->v2->vec.y; dist= PdistVL2Dfl(vec1, vec2, vec3); if(se==se1 || se==se2 || se==se3 || se==se4) dist-= 5.0; if(distnext; } if(curedge==0) return; cursonedge= 1; if(curedge->v1->vec.x==curedge->v2->vec.x) glutSetCursor(GLUT_CURSOR_LEFT_RIGHT); else glutSetCursor(GLUT_CURSOR_UP_DOWN); } void areawinset(short win) { ScrArea *sa= 0; SpaceSeq *sseq; if(win>3) { curarea= areawinar[win]; if(curarea==0) { printf("error in areawinar %d ,areawinset\n", win); return; } switch(curarea->spacetype) { case SPACE_VIEW3D: G.vd= curarea->spacedata.first; break; case SPACE_IPO: if(G.sipo != curarea->spacedata.first) allqueue(REDRAWBUTSANIM, 0); G.sipo= curarea->spacedata.first; G.v2d= &G.sipo->v2d; break; case SPACE_BUTS: G.buts= curarea->spacedata.first; G.v2d= &G.buts->v2d; break; case SPACE_SEQ: sseq= curarea->spacedata.first; G.v2d= &sseq->v2d; case SPACE_OOPS: G.soops= curarea->spacedata.first; G.v2d= &G.soops->v2d; break; case SPACE_IMASEL: break; case SPACE_IMAGE: G.sima= curarea->spacedata.first; G.v2d= &G.sima->v2d; break; case SPACE_PAINT: break; case SPACE_FILE: break; case SPACE_TEXT: G.stext= curarea->spacedata.first; break; case SPACE_SOUND: G.ssound= curarea->spacedata.first; G.v2d= &G.ssound->v2d; break; } } if(win) mywinset(win); } void headerbox(int selcol, int width) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if(selcol) glClearColor(.75, .75, .75, 0.0); else glClearColor(.65, .65, .65, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3ub(0, 0, 0); sdrawbox(0, 0, width, HEADERY); glColor3ub(220, 220, 220); sdrawline(0, HEADERY-1, width, HEADERY-1); glColor3ub(176, 176, 176); sdrawline(0, HEADERY-2, width, HEADERY-2); glColor3ub(128, 128, 128); sdrawline(0, 2, width, 2); glColor3ub(64, 64, 64); sdrawline(0, 1, width, 1); glColor3ub(0, 0, 0); sdrawline(0, 0, width, 0); } void defheaddraw() { int selcol; /* aktieve kleur */ selcol= 0; if(G.curscreen->winakt) { if(curarea->headwin == G.curscreen->winakt) selcol= 1; else if(curarea->win == G.curscreen->winakt) selcol= 1; } headerbox(selcol, curarea->winx+100); /* buttons, functies in window.c */ switch(curarea->spacetype) { case SPACE_EMPTY: break; case SPACE_FILE: file_buttons(); break; case SPACE_INFO: info_buttons(); break; case SPACE_VIEW3D: view3d_buttons(); break; case SPACE_IPO: ipo_buttons(); break; case SPACE_BUTS: buts_buttons(); break; case SPACE_SEQ: seq_buttons(); break; case SPACE_IMAGE: image_buttons(); break; case SPACE_IMASEL: imasel_buttons(); break; case SPACE_OOPS: oops_buttons(); break; case SPACE_PAINT: break; case SPACE_TEXT: text_buttons(); break; case SPACE_SOUND: sound_buttons(); break; } curarea->head_swap= WIN_BACK_OK; } void defwindraw() { if(curarea->win && curarea->windraw) { curarea->windraw(); } else { glClearColor(0.4375, 0.4375, 0.4375, 0.0); glClear(GL_COLOR_BUFFER_BIT); } curarea->win_swap= WIN_BACK_OK; } void defheadchange() { float ofs; if(curarea->headchange) { curarea->headchange(); } else { ofs= curarea->headbutofs; if(curarea->headertype==HEADERDOWN) ortho2(-0.5+ofs, curarea->headrct.xmax-curarea->headrct.xmin-0.5+ofs, +0.6, curarea->headrct.ymax-curarea->headrct.ymin+0.6); else ortho2(-0.5+ofs, curarea->headrct.xmax-curarea->headrct.xmin-0.5+ofs, -0.5, curarea->headrct.ymax-curarea->headrct.ymin-0.5); } } void defwinchange() { if(curarea->winchange) { curarea->winchange(); } else { ortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5); glLoadIdentity(); } } void defwinmat() { ortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5); glLoadIdentity(); } void headmenu(ScrArea *sa) { float fac; short val; if(curarea->full) { confirm("", "Full window"); return; } val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0"); if(val> -1) { sa->headertype= val; testareas(); winqueue_break= 1; } } void defheadqread(ScrArea *sa) { ScrArea *tempsa; float fac; ushort event; short val, do_redraw=0, do_change=0; char *str; if(sa->headertype==0) return; areawinset(sa->headwin); while(sa->hq != sa->headqueue) { sa->hq-= 2; event= (ushort)sa->hq[0]; val= sa->hq[1]; if(val) { if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; switch(event) { case UI_BUT_EVENT: do_headerbuttons(val); break; case LEFTMOUSE: mywinset(G.curscreen->mainwin); if(G.qual & LR_CTRLKEY) glutPushWindow(); else { glutPopWindow(); glutDoWorkList(); R.winpop= 1; /* flag: need pop */ } areawinset(sa->headwin); break; case MIDDLEMOUSE: scrollheader(); break; case RIGHTMOUSE: headmenu(sa); break; case REDRAW: do_redraw= 1; break; case CHANGED: sa->head_swap= 0; do_change= 1; do_redraw= 1; break; default: if(sa->headqread) sa->headqread(event, val); } if(winqueue_break) return; } } /* test: bestaat window nog */ tempsa= areawinar[sa->headwin]; if(tempsa==0) return; /* dit onderscheid loopt niet lekker... */ if(do_change || do_redraw) { areawinset(sa->headwin); defheadchange(); if(sa->headdraw) sa->headdraw(); } } ushort winqtest(ScrArea *sa) { if(sa->win && sa->wq != sa->winqueue) return (ushort) sa->wq[-2]; if(sa->headwin && sa->hq != sa->headqueue) return (ushort) sa->hq[-2]; return 0; } ushort headqtest(ScrArea *sa) { if(sa->headwin && sa->hq != sa->headqueue) return (ushort) sa->hq[-2]; return 0; } void winqdelete(ScrArea *sa) { if(sa->wq != sa->winqueue) sa->wq-= 2; } void winqclear(ScrArea *sa) { sa->wq = sa->winqueue; } void defwinqread(ScrArea *sa) { ScrArea *tempsa; ushort event; short val, do_redraw=0, do_change=0; if(sa!=curarea || sa->win!=winget()) areawinset(sa->win); while(sa->wq != sa->winqueue) { sa->wq-= 2; event= (ushort) sa->wq[0]; val= sa->wq[1]; if(event==REDRAW) { do_redraw= 1; } else if(event==CHANGED) { sa->win_swap= 0; do_change= 1; do_redraw= 1; } else { if(sa->winqread) sa->winqread(event, val); } if(winqueue_break) return; } /* test: bestaat window nog */ tempsa= areawinar[sa->win]; if(tempsa==0) return; if(do_change || do_redraw) areawinset(sa->win); if(do_change) defwinchange(); if(do_redraw) defwindraw(); } void addqueue(short win, ushort event, short val) { ScrArea *sa; long size; short *end; /* nieuwe events worden vooraan in het array gezet */ sa= areawinar[win]; if(sa) { if(win==sa->headwin) { end= sa->headqueue + MAXQUEUE-2; if( (long)sa->hq < (long)end) { size= ((long)sa->hq)-((long)sa->headqueue); if(size) memmove( sa->headqueue+2, sa->headqueue, size); ((ushort *)sa->headqueue)[0]= event; sa->headqueue[1]= val; sa->hq+= 2; } } else if(win==sa->win) { end= sa->winqueue + MAXQUEUE-2; if( (long)sa->wq < (long)end) { size= ((long)sa->wq)-((long)sa->winqueue); if(size) memmove( sa->winqueue+2, sa->winqueue, size); ((ushort *)sa->winqueue)[0]= event; sa->winqueue[1]= val; sa->wq+= 2; } } } } short afterqueue[3*MAXQUEUE], *afterq=afterqueue; void addafterqueue(short win, ushort event, short val) { long poin; poin= (long)afterqueue; poin+= 6*(MAXQUEUE-1); if( (long)afterq < poin ) { afterq[0]= win; ((ushort *)afterq)[1]= event; afterq[2]= val; afterq+= 3; } } void append_afterqueue() { while( afterqueue != afterq) { afterq-= 3; addqueue(afterq[0], afterq[1], afterq[2]); } } int afterqtest() { if(afterqueue != afterq) return 1; return 0; } void remake_qual() { G.qual= get_qual(); } char ext_load_str[256]= {0, 0}; void add_readfile_event(char *filename) { qenter(LOAD_FILE, 1); strcpy(ext_load_str, filename); convertstringcode(ext_load_str); } short ext_redraw=0, ext_inputchange=0, ext_mousemove=0, in_ext_qread=0; ushort screen_qread(short *val) { static int oldwin= 0; ScrArea *sa; bWindow *win; ushort event; short newwin, rt, devs[2], vals[2]; event= 0; if(in_ext_qread==0) { if(ext_inputchange) { *val= ext_inputchange; ext_inputchange= 0; event= INPUTCHANGE; } else if(ext_redraw) { *val= ext_redraw; ext_redraw= 0; event= REDRAW; } else if(ext_mousemove) { ext_mousemove= 0; event= MOUSEY; } else if(afterqueue!=afterq && qtest()==0 ) { *val= 0; event= AFTERQUEUE; } } if(event==0 ) { while(myqtest()==0) { int ww= 0; /* Patch from Zr, processEventsAndTimeouts returns nonzero if it has failed to get an event and is hanging */ if (processEventsAndTimeouts()) return 0; glutDoWorkList(); if(myqtest()==0) usleep(1); } event= qread(val); } /* if(event==0) { */ /* while(myqtest()==0) { */ /* if(qtest()) { */ /* processEventsAndTimeouts(); */ /* glutDoWorkList(); */ /* if(myqtest()==0) usleep(1); */ /* } */ /* if(myqtest()==0) if(R.flag & R_RENDERING) return 0; */ /* } */ /* event= qread(val); */ /* } */ if(G.curscreen==0) return event; if(event==Q_FIRSTTIME) { glutDoWorkList(); } else if(event==RIGHTSHIFTKEY || event== LEFTSHIFTKEY) { if(*val) G.qual |= LR_SHIFTKEY; else G.qual &= ~LR_SHIFTKEY; } else if(event==RIGHTALTKEY || event== LEFTALTKEY) { if(*val) G.qual |= LR_ALTKEY; else G.qual &= ~LR_ALTKEY; } else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) { if(*val) G.qual |= LR_CTRLKEY; else G.qual &= ~LR_CTRLKEY; } else if(event==WINFREEZE || event==WINTHAW) { if((R.flag & R_RENDERING)==0) { if(R.win) winclose(R.win); R.win= 0; G.qual= 0; } } else if(event==INPUTCHANGE || event==REDRAW || event==DRAWEDGES) { /* DRAWEDGES: komt vanuit setscreen, qual opnieuw berekenen */ if(*val==1) remake_qual(); if(event==INPUTCHANGE && in_ext_qread==0) { if(*val) { mywinset(*val); G.curscreen->winakt= *val; oldwin= *val; } oldwin= 0; } if(event==REDRAW ) { /* kunstmatige mousy voor herberekenen winakt (als b.v. R.win naar achter gepusht */ qenter(MOUSEY, scrmousey); } } else if(event==MOUSEX || event==MOUSEY) { if(event==MOUSEY && in_ext_qread==0 && (R.win==0 || G.curscreen->winakt!=R.win)) { /* testen waar muis staat */ newwin= 0; win= swindowbase.first; while(win) { if(scrmousex>win->xmin && scrmousexxmax) { /* deze uitzondering betreft onderste en bovenste edge: voor edit cursonedge */ if( (scrmousey==0 && scrmousey==win->ymin) || (scrmousey==G.curscreen->endy && scrmousey==win->ymax)) { if(scrmousey>win->ymin && scrmouseyymax) { newwin= win->id; break; } } else if(scrmousey>=win->ymin && scrmousey<=win->ymax) { newwin= win->id; break; } } win= win->next; } /* cursor */ if(newwin != oldwin) { if(newwin==0) { set_cursonedge(scrmousex, scrmousey); } else if(oldwin==0) { cursonedge= 0; } if(newwin) { sa= areawinar[newwin]; if(sa->win==newwin) glutSetCursor(sa->cursor); else glutSetCursor(CURSOR_STD); } } else if(newwin==0 && oldwin==0) { set_cursonedge(scrmousex, scrmousey); } /* else if (scrmousex<2 || scrmousey<2 || abs(scrmousex - G.curscreen->sizex)<2|| abs(scrmousey - G.curscreen->sizey)<2) { set_cursonedge(scrmousex, scrmousey); } */ if(newwin!=0) { if(newwin != oldwin || G.curscreen->winakt==0) { event= INPUTCHANGE; *val= newwin; } } oldwin= newwin; } } else if(event==TIMER0) { event= 0; if(in_ext_qread==0) { write_autosave(); autosavetime= 0; } } else if(event==LOAD_FILE) { char ext_load_str_cp[256]; event= 0; strcpy(ext_load_str_cp, ext_load_str); ext_load_str[0]=0; read_file(ext_load_str_cp); } return event; } ushort special_qread(short *val) { /* simul alternatief voor extern_qread */ ushort event; in_ext_qread= 1; /* niet zo net, wel zo handig (zie screen_qread) */ event= screen_qread(val); in_ext_qread= 0; if(event==REDRAW) ext_redraw= *val; else if(event==INPUTCHANGE) ext_inputchange= *val; else if(event==MOUSEY || event==MOUSEX) { ext_mousemove= 1; event= 0; } return event; } short ext_qtest() { if(ext_inputchange) return INPUTCHANGE; else if(ext_redraw) return REDRAW; else if(ext_mousemove) return MOUSEY; else return myqtest(); } ushort extern_qread(short *val) { /* bewaart de laatste INPUTCHANGE en de laatste REDRAW */ ushort event; in_ext_qread= 1; /* niet zo net, wel zo handig (zie screen_qread) */ event= screen_qread(val); if(event==REDRAW) ext_redraw= *val; else if(event==INPUTCHANGE) ext_inputchange= *val; else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1; else if(event==RIGHTSHIFTKEY || event== LEFTSHIFTKEY) { if(*val) G.qual |= LR_SHIFTKEY; else G.qual &= ~LR_SHIFTKEY; } else if(event==RIGHTALTKEY || event== LEFTALTKEY) { if(*val) G.qual |= LR_ALTKEY; else G.qual &= ~LR_ALTKEY; } else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) { if(*val) G.qual |= LR_CTRLKEY; else G.qual &= ~LR_CTRLKEY; } else if(G.qual & LR_CTRLKEY && event==F3KEY) { RE_screendump(); } in_ext_qread= 0; return event; } void markdirty_all() { ScrArea *sa; sa= G.curscreen->areabase.first; while(sa) { if(sa->win) { addqueue(sa->win, REDRAW, 1); sa->win_swap &= ~WIN_FRONT_OK; } if(sa->headwin) { addqueue(sa->headwin, REDRAW, 1); sa->head_swap &= ~WIN_FRONT_OK; } sa= sa->next; } } /* BePatch! glutGetFrontbuffer is defined by glDrawBuffer! In fact the name is wrong... */ void header_front_to_back_glut(ScrArea *sa) { glDrawBuffer(GL_FRONT); glRasterPos2f( (float) sa->headrct.xmin -0.1, (float) sa->headrct.ymin-0.1); glutGetFrontBuffer(sa->headrct.xmin, sa->headrct.ymin, sa->winx, HEADERY-1); glDrawBuffer(GL_BACK); glutPutFrontBuffer(); sa->head_swap= WIN_EQUAL; } void window_front_to_back_glut(ScrArea *sa) { glDrawBuffer(GL_FRONT); glRasterPos2f( (float) sa->winrct.xmin -0.1, (float) sa->winrct.ymin-0.1); glutGetFrontBuffer(sa->winrct.xmin, sa->winrct.ymin, sa->winx, sa->winy); glDrawBuffer(GL_BACK); glutPutFrontBuffer(); sa->win_swap= WIN_EQUAL; } void header_back_to_front_glut(ScrArea *sa) { glDrawBuffer(GL_BACK); glRasterPos2f( (float) sa->headrct.xmin -0.1, (float) sa->headrct.ymin-0.1); glutGetFrontBuffer(sa->headrct.xmin, sa->headrct.ymin, sa->winx, HEADERY-1); glDrawBuffer(GL_FRONT); glutPutFrontBuffer(); glDrawBuffer(GL_BACK); sa->head_swap= WIN_EQUAL; } /* sgi */ void header_front_to_back_ogl(ScrArea *sa) { glReadBuffer(GL_FRONT); glRasterPos2f( (float) sa->headrct.xmin -0.1, (float) sa->headrct.ymin-0.1); glCopyPixels(sa->headrct.xmin, sa->headrct.ymin, sa->winx, HEADERY, GL_COLOR); sa->head_swap= WIN_EQUAL; glReadBuffer(GL_BACK); } void window_front_to_back_ogl(ScrArea *sa) { glReadBuffer(GL_FRONT); glRasterPos2f( (float) sa->winrct.xmin -0.1, (float) sa->winrct.ymin-0.1); glCopyPixels(sa->winrct.xmin, sa->winrct.ymin, sa->winx, sa->winy, GL_COLOR); sa->win_swap= WIN_EQUAL; glReadBuffer(GL_BACK); } void header_back_to_front_ogl(ScrArea *sa) { glDrawBuffer(GL_FRONT); glRasterPos2f( (float) sa->headrct.xmin -0.1, (float) sa->headrct.ymin-0.1); glCopyPixels(sa->headrct.xmin, sa->headrct.ymin, sa->winx, HEADERY, GL_COLOR); sa->head_swap= WIN_EQUAL; glDrawBuffer(GL_BACK); } void screen_swapbuffers_OGL() { ScrArea *sa; int doswap= 0, headswap=0, oldwin; /* test op swap */ sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap==WIN_BACK_OK) doswap= 1; if(sa->headertype==0) sa->head_swap= WIN_EQUAL; else if(sa->head_swap==WIN_BACK_OK) headswap= 1; sa= sa->next; } if(doswap==0 && headswap==0) return; oldwin= winget(); mywinset(G.curscreen->mainwin); if(doswap) { sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap== WIN_FRONT_OK) window_front_to_back_ogl(sa); if(sa->head_swap== WIN_FRONT_OK) header_front_to_back_ogl(sa); sa= sa->next; } myswapbuffers(); } /* headers moeten in front en back gelijk zijn: dus: */ /* heads van back naar frontbuffer? of omgekeerd? */ sa= G.curscreen->areabase.first; while(sa) { if(sa->head_swap==WIN_FRONT_OK) { header_front_to_back_ogl(sa); } else if(sa->head_swap==WIN_BACK_OK) { header_back_to_front_ogl(sa); } sa= sa->next; } if(oldwin) areawinset(oldwin); } void screen_swapbuffers_GLUT() { ScrArea *sa; int doswap= 0, headswap=0, oldwin; /* test op swap */ sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap==WIN_BACK_OK) doswap= 1; if(sa->headertype==0) sa->head_swap= WIN_EQUAL; else if(sa->head_swap==WIN_BACK_OK) headswap= 1; sa= sa->next; } if(doswap==0 && headswap==0) return; oldwin= winget(); mywinset(G.curscreen->mainwin); if(doswap) { sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap== WIN_FRONT_OK) window_front_to_back_glut(sa); if(sa->head_swap== WIN_FRONT_OK) header_front_to_back_glut(sa); sa= sa->next; } myswapbuffers(); } /* headers moeten in front en back gelijk zijn: dus: */ /* heads van back naar frontbuffer? of omgekeerd? */ sa= G.curscreen->areabase.first; while(sa) { if(sa->head_swap==WIN_FRONT_OK) { header_front_to_back_glut(sa); } else if(sa->head_swap==WIN_BACK_OK) { header_back_to_front_glut(sa); } sa= sa->next; } if(oldwin) areawinset(oldwin); } void screen_swapbuffers_REDRAW() { ScrArea *sa; int oldwin, doswap= 0, swap; oldwin= winget(); /* dit is een nieuwe implementatie: uitsluitend met redraws en normale swapbuffer */ /* allemaal front ok? */ sa= G.curscreen->areabase.first; while(sa) { if(sa->win && (sa->win_swap & WIN_FRONT_OK)==0) break; if(sa->headertype==0) sa->head_swap= WIN_EQUAL; if((sa->head_swap & WIN_FRONT_OK)==0) break; sa= sa->next; } if(sa==0) return; /* printf("front not OK %d %d %d %d\n", sa->win, sa->win_swap, sa->headwin, sa->head_swap); */ sa= G.curscreen->areabase.first; while(sa) { swap= sa->win_swap; if( (swap & WIN_BACK_OK) == 0) { if(sa->win && sa->windraw) { areawinset(sa->win); sa->windraw(); doswap= 1; } sa->win_swap= swap | WIN_BACK_OK; } else if( sa->win_swap==WIN_BACK_OK) doswap= 1; swap= sa->head_swap; if( (swap & WIN_BACK_OK) == 0) { areawinset(sa->headwin); if(sa->headdraw) sa->headdraw(); doswap= 1; sa->head_swap = swap | WIN_BACK_OK; } else if( sa->head_swap==WIN_BACK_OK) doswap= 1; sa= sa->next; } /* de hele backbuffer moet nu OK zijn */ if(doswap) { myswapbuffers(); } if(oldwin) areawinset(oldwin); } void screen_swapbuffers_MESA() { ScrArea *sa; /* dit is een nieuwe implementatie: uitsluitend met partial swap */ /* test op swap */ sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap==WIN_BACK_OK) { myCopySubBuffer(sa->winrct.xmin, sa->winrct.ymin-1, sa->winx, sa->winy); sa->win_swap= WIN_EQUAL; } if(sa->headertype==0) sa->head_swap= WIN_EQUAL; else if(sa->head_swap==WIN_BACK_OK) { myCopySubBuffer(sa->headrct.xmin, sa->headrct.ymin-1, sa->winx, HEADERY); sa->head_swap= WIN_EQUAL; } sa= sa->next; } } void screen_swapbuffers() { ScrArea *sa; int oldwin; #ifdef __sgi screen_swapbuffers_OGL(); #endif #if defined __linux__ || defined __FreeBSD__ #ifdef MESA30 screen_swapbuffers_MESA(); #else screen_swapbuffers_REDRAW(); #endif #endif #ifdef __WIN32 screen_swapbuffers_REDRAW(); #endif #ifdef __BeOS screen_swapbuffers_GLUT(); #endif #ifdef __SUN screen_swapbuffers_OGL(); #endif } int is_allowed_to_change_screen(bScreen *new) { /* niet als curscreen is full * niet als obedit && old->scene!=new->scene */ if(new==0) return 0; if(G.curscreen->full) return 0; if(curarea->full) return 0; if(G.obedit) { if(G.curscreen->scene!=new->scene) return 0; } return 1; } void splash() { extern char datatoc_splash_jpg[]; extern int datatoc_splash_jpg_size; ImBuf *bbuf; int oldwin; bbuf= loadiffmem((int*)datatoc_splash_jpg, LI_rect); bbuf= ibImageFromMemory((int *)datatoc_splash_jpg, datatoc_splash_jpg_size, LI_rect); if(bbuf==0) { printf("Can't load buttonimage\n"); exit(0); } oldwin = mywinget(); mywinset(G.curscreen->mainwin); glDrawBuffer(GL_FRONT); glRasterPos2i( (prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2 ); glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect); glFinish(); glDrawBuffer(GL_BACK); freeImBuf(bbuf); usleep(10); while(qtest()==0) usleep(2); mywinset(oldwin); markdirty_all(); } void screenmain() { static int firsttime= 1; extern int Xqual; ScrArea *sa, *sa1, *sa2; bScreen *sc; float fac; int wx, wy, orx, ory; ushort event; short a, val, towin, inqueue, debugval= 0; while(qtest() || afterqtest() ) { event= screen_qread(&val); towin= event; if( (G.f & G_DEBUG) && event && event!=MOUSEY && event!=MOUSEX) { PRINT3(d, d, d, event, val, G.qual); debugval= 1; } if(val && cursonedge) { if(event==LEFTMOUSE) { moveareas(); towin= 0; } else if(event==MIDDLEMOUSE || event==RIGHTMOUSE) { if(curarea->headertype==0) val= pupmenu("Split Area|Join Areas|Add header"); else val= pupmenu("Split Area|Join Areas"); if(val==1) editsplitpoint(); else if(val==2) joinarea(curarea); else if(val==3) { curarea->headertype= HEADERDOWN; testareas(); } towin= 0; } } else if(event==QKEY) { if((G.obedit && G.obedit->type==OB_FONT && curarea->spacetype==SPACE_VIEW3D)||curarea->spacetype==SPACE_TEXT); else { if(val && okee("QUIT BLENDER")) exit_usiblender(); towin= 0; } } else if(event==SPACEKEY) { if((G.obedit && G.obedit->type==OB_FONT && curarea->spacetype==SPACE_VIEW3D)||curarea->spacetype==SPACE_TEXT); else { if(val) toolbox(); towin= 0; } } else if(event==INPUTCHANGE) { /* welke headers moeten redraw? */ if(val>3) { /* eerste drie nummers voor GL */ if( G.curscreen->winakt != val ) { /* de oude en nieuwe area */ sa1= areawinar[G.curscreen->winakt]; sa2= areawinar[val]; if(sa1==sa2); else { if(sa1) addqueue(sa1->headwin, REDRAW, 1); if(sa2) addqueue(sa2->headwin, REDRAW, 1); } } /* testen of window nog bestaat (oude event bij join b.v.) */ if(areawinar[val]) { /* als winakt==R.win mag alleen een GL-INPUTCHANGE winakt zetten */ if(R.win==0 || G.curscreen->winakt!=R.win) G.curscreen->winakt= val; clear_global_filesel_vars(); } else { G.curscreen->winakt= 0; } } towin= 0; } else if(event==DRAWEDGES) { towin= 0; dodrawscreen= 1; } else if(event==REDRAW) { towin= 0; if(val==G.curscreen->mainwin) { markdirty_all(); dodrawscreen= 1; } else if(val>3) { addqueue(val, REDRAW, val); } else if(R.win && val==R.win) { mywinset(R.win); getorigin(&orx, &ory); R.winxof= orx; R.winyof= ory; RE_redraw_render_win(val); } } else if(event==RIGHTARROWKEY) { if(val && (G.qual & LR_CTRLKEY)) { sc= G.curscreen->id.next; if(is_allowed_to_change_screen(sc)) setscreen(sc); towin= 0; } } else if(event==LEFTARROWKEY) { if(val && (G.qual & LR_CTRLKEY)) { sc= G.curscreen->id.prev; if(is_allowed_to_change_screen(sc)) setscreen(sc); towin= 0; } } else if(event==UPARROWKEY || event==DOWNARROWKEY) { if(val && (G.qual & LR_CTRLKEY)) { area_fullscreen(); towin= 0; } } else if(event==AFTERQUEUE) { append_afterqueue(); } if(towin) { towin= blenderqread(event, val); if(towin && G.curscreen->winakt) addqueue(G.curscreen->winakt, event, val); } /* window queues en swapbuffers */ event= ext_qtest(); if(visible==0) event= 0; /* when screen window is invisible, don't enter queues */ if(event==0 || event==EXECUTE) { /* || event==MOUSEY ?? */ inqueue= 1; while(inqueue) { inqueue= 0; winqueue_break= 0; sa= G.curscreen->areabase.first; while(sa) { /* bewust eerst header afhandelen, dan rest. Header is soms init */ if(sa->headwin && sa->headqueue!=sa->hq) { defheadqread(sa); inqueue= 1; } if(winqueue_break) { /* mogelijk nieuwe G.curscreen */ inqueue= 1; break; } if(sa->win && sa->winqueue!=sa->wq) { defwinqread(sa); inqueue= 1; } if(winqueue_break) { /* mogelijk nieuwe G.curscreen */ inqueue= 1; break; } sa= sa->next; } } if(dodrawscreen) { drawscreen(); dodrawscreen= 0; } screen_swapbuffers(); } /* restore actieve area */ if(G.curscreen->winakt != winget()) areawinset(G.curscreen->winakt); } /* de enige idle */ usleep(2); if(firsttime) { extern int installed_blend; /* readfile.c */ if(G.versionfile>=G.version && installed_blend==0); else splash(); firsttime= 0; } if(debugval==1 && (G.f & G_DEBUG)) { debugval= glGetError(); while( debugval!=GL_NO_ERROR) { printf("GL_ERROR: %d %s\n", debugval, gluErrorString(debugval)); debugval= glGetError(); } printf("end screenmain\n"); } } /* ********* AREAS ************* */ void getdisplaysize() { displaysizex= glutGet(GLUT_SCREEN_WIDTH); displaysizey= glutGet(GLUT_SCREEN_HEIGHT); } void setprefsize(int stax, int stay, int sizx, int sizy) { if(stax<0) stax= 0; if(stay<0) stay= 0; if(sizx<320) sizx= 320; if(sizy<256) sizy= 256; if(stax+sizx>displaysizex) sizx= displaysizex-stax; if(stay+sizy>displaysizey) sizy= displaysizey-stay; if(sizx<320 || sizy<256) { printf("ERROR: illegal prefsize\n"); return; } prefstax= stax; prefstay= stay; prefsizx= sizx; prefsizy= sizy; } ScrArea *findcurarea() { ScrArea *sa; short mval[2]; getmouseco_sc(mval); sa= G.curscreen->areabase.first; while(sa) { if(sa->v1->vec.x<=mval[0] && sa->v3->vec.x>=mval[0]) { if(sa->v1->vec.y<=mval[1] && sa->v2->vec.y>=mval[1]) { return sa; } } sa= sa->next; } return 0; } ScrVert *addscrvert(ListBase *lb, short x, short y) { ScrVert *sv; sv= callocN(sizeof(ScrVert), "addscrvert"); sv->vec.x= x; sv->vec.y= y; if(lb) addtail(lb, sv); return sv; } void sortscrvert(ScrVert **v1, ScrVert **v2) { ScrVert *tmp; if ((long)*v1 > (long)*v2) { tmp= *v1; *v1= *v2; *v2= tmp; } } ScrEdge *addscredge(ListBase *lb, ScrVert *v1, ScrVert *v2) { ScrEdge *se; se= callocN(sizeof(ScrEdge), "addscredge"); sortscrvert(&v1, &v2); se->v1= v1; se->v2= v2; if(lb) addtail(lb, se); return se; } ScrEdge *findscredge(ScrVert *v1, ScrVert *v2) { ScrVert *sv; ScrEdge *se; sortscrvert(&v1, &v2); se= G.curscreen->edgebase.first; while(se) { if(se->v1==v1 && se->v2==v2) return se; se= se->next; } return 0; } ScrEdge *findscredge_sc(bScreen *sc, ScrVert *v1, ScrVert *v2) { ScrVert *sv; ScrEdge *se; sortscrvert(&v1, &v2); se= sc->edgebase.first; while(se) { if(se->v1==v1 && se->v2==v2) return se; se= se->next; } return 0; } void removedouble_scrverts() { ScrVert *v1, *verg; ScrEdge *se; ScrArea *sa; verg= G.curscreen->vertbase.first; while(verg) { if(verg->newv==0) { /* !!! */ v1= verg->next; while(v1) { if(v1->newv==0) { /* !?! */ if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) { /* printf("doublevert\n"); */ v1->newv= verg; } } v1= v1->next; } } verg= verg->next; } /* vervang pointers in edges en vlakken */ se= G.curscreen->edgebase.first; while(se) { if(se->v1->newv) se->v1= se->v1->newv; if(se->v2->newv) se->v2= se->v2->newv; /* edges zijn veranderd: dus.... */ sortscrvert(&(se->v1), &(se->v2)); se= se->next; } sa= G.curscreen->areabase.first; while(sa) { if(sa->v1->newv) sa->v1= sa->v1->newv; if(sa->v2->newv) sa->v2= sa->v2->newv; if(sa->v3->newv) sa->v3= sa->v3->newv; if(sa->v4->newv) sa->v4= sa->v4->newv; sa= sa->next; } /* verwijderen */ verg= G.curscreen->vertbase.first; while(verg) { v1= verg->next; if(verg->newv) { remlink(&G.curscreen->vertbase, verg); freeN(verg); } verg= v1; } } void removenotused_scrverts() { ScrVert *sv, *svn; ScrEdge *se; ScrArea *sa; /* ga ervan uit dat de edges goed zijn */ se= G.curscreen->edgebase.first; while(se) { se->v1->flag= 1; se->v2->flag= 1; se= se->next; } sv= G.curscreen->vertbase.first; while(sv) { svn= sv->next; if(sv->flag==0) { remlink(&G.curscreen->vertbase, sv); freeN(sv); } else sv->flag= 0; sv= svn; } } void removedouble_scredges() { ScrVert *v1; ScrEdge *verg, *se, *sn; /* vergelijken */ verg= G.curscreen->edgebase.first; while(verg) { se= verg->next; while(se) { sn= se->next; if(verg->v1==se->v1 && verg->v2==se->v2) { remlink(&G.curscreen->edgebase, se); freeN(se); } se= sn; } verg= verg->next; } } void removenotused_scredges() { ScrVert *sv; ScrEdge *se, *sen; ScrArea *sa; int a=0; /* zet flag als edge gebruikt wordt in area */ sa= G.curscreen->areabase.first; while(sa) { se= findscredge(sa->v1, sa->v2); if(se==0) printf("error: area %d edge 1 bestaat niet\n", a); else se->flag= 1; se= findscredge(sa->v2, sa->v3); if(se==0) printf("error: area %d edge 2 bestaat niet\n", a); else se->flag= 1; se= findscredge(sa->v3, sa->v4); if(se==0) printf("error: area %d edge 3 bestaat niet\n", a); else se->flag= 1; se= findscredge(sa->v4, sa->v1); if(se==0) printf("error: area %d edge 4 bestaat niet\n", a); else se->flag= 1; sa= sa->next; a++; } se= G.curscreen->edgebase.first; while(se) { sen= se->next; if(se->flag==0) { remlink(&G.curscreen->edgebase, se); freeN(se); } else se->flag= 0; se= sen; } } void calc_arearcts(ScrArea *sa) { if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+EDGEWIDTH2+1; else sa->totrct.xmin= sa->v1->vec.x; if(sa->v4->vec.xsizex-1) sa->totrct.xmax= sa->v4->vec.x-EDGEWIDTH2-1; else sa->totrct.xmax= sa->v4->vec.x; if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+EDGEWIDTH2+1; else sa->totrct.ymin= sa->v1->vec.y; if(sa->v2->vec.ysizey-1) sa->totrct.ymax= sa->v2->vec.y-EDGEWIDTH2-1; else sa->totrct.ymax= sa->v2->vec.y; sa->winrct= sa->totrct; if(sa->headertype) { sa->headrct= sa->totrct; if(sa->headertype==HEADERDOWN) { sa->headrct.ymax= sa->headrct.ymin+HEADERY-1; sa->winrct.ymin= sa->headrct.ymax+1; } else if(sa->headertype==HEADERTOP) { sa->headrct.ymin= sa->headrct.ymax-HEADERY+1; sa->winrct.ymax= sa->headrct.ymin-1; } } if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax; /* als speedup voor berekeningen */ sa->winx= sa->winrct.xmax-sa->winrct.xmin+1; sa->winy= sa->winrct.ymax-sa->winrct.ymin+1; } void openheadwin(ScrArea *sa) { sa->headwin= myswinopen(G.curscreen->mainwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax); glMatrixMode(GL_MODELVIEW); if(sa->headqueue==0) sa->headqueue= sa->hq= mallocN(sizeof(short)*MAXQUEUE, "headqueue"); areawinar[sa->headwin]= sa; /* anders doet addqueue het niet */ addqueue(sa->headwin, CHANGED, 1); } void openareawin(ScrArea *sa) { sa->win= myswinopen(G.curscreen->mainwin, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax); if(sa->winqueue==0) sa->winqueue= sa->wq= mallocN(sizeof(short)*MAXQUEUE, "winqueue"); areawinar[sa->win]= sa; /* anders doet addqueue het niet */ addqueue(sa->win, CHANGED, 1); } void closeheadwin(ScrArea *sa) { if(G.curscreen && sa->headwin==G.curscreen->winakt) G.curscreen->winakt= 0; if(sa->headwin) winclose(sa->headwin); sa->headwin= 0; sa->headdraw= NULL; if(sa->headqueue) { freeN(sa->headqueue); sa->headqueue= sa->hq= 0; } } void closeareawin(ScrArea *sa) { if(G.curscreen && sa->win==G.curscreen->winakt) G.curscreen->winakt= 0; uiFreeBlocksWin(&sa->uiblocks, sa->win); if(sa->win) winclose(sa->win); sa->win= 0; sa->windraw= NULL; if(sa->winqueue) { freeN(sa->winqueue); sa->winqueue= sa->wq= 0; } } void del_area(ScrArea *sa) { closeareawin(sa); closeheadwin(sa); freespacelist(&sa->spacedata); uiFreeBlocks(&sa->uiblocks); } void copy_areadata(ScrArea *sa1, ScrArea *sa2) { sa1->headertype= sa2->headertype; sa1->spacetype= sa2->spacetype; sa1->butspacetype= sa2->spacetype; sa1->headdraw= sa2->headdraw; sa1->windraw= sa2->windraw; sa1->headqread= sa2->headqread; sa1->winqread= sa2->winqread; sa1->headchange= sa2->headchange; sa1->winchange= sa2->winchange; Mat4CpyMat4(sa1->winmat, sa2->winmat); freespacelist(&sa1->spacedata); duplicatespacelist(&sa1->spacedata, &sa2->spacedata); } ScrArea *addscrarea(ListBase *lb, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype) { ScrArea *sa; sa= callocN(sizeof(ScrArea), "addscrarea"); sa->cursor= CURSOR_STD; sa->v1= v1; sa->v2= v2; sa->v3= v3; sa->v4= v4; sa->headertype= headertype; sa->spacetype= sa->butspacetype= spacetype; calc_arearcts(sa); if(headertype) openheadwin(sa); if(sa->winrct.yminwinrct.ymax) openareawin(sa); if(lb) addtail(lb, sa); return sa; } void testareas() { ScrArea *sa; rcti tempw, temph; /* testen of header er moet zijn, of weg moet, of verplaatst */ /* testen of window er moet zijn, of weg moet, of verplaatst */ sa= G.curscreen->areabase.first; while(sa) { tempw= sa->winrct; temph= sa->headrct; calc_arearcts(sa); /* test header */ if(sa->headertype) { if(sa->headwin==0) { openheadwin(sa); set_func_space(sa); } else { /* is header op goede plek? */ if(temph.xmin!=sa->headrct.xmin || temph.xmax!=sa->headrct.xmax || temph.ymin!=sa->headrct.ymin || temph.ymax!=sa->headrct.ymax) { addqueue(sa->headwin, CHANGED, 1); mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax); } if(sa->headbutlenwinx) { sa->headbutofs= 0; addqueue(sa->headwin, CHANGED, 1); } else if(sa->headbutofs+sa->winx > sa->headbutlen) { sa->headbutofs= sa->headbutlen-sa->winx; addqueue(sa->headwin, CHANGED, 1); } } } else { if(sa->headwin) closeheadwin(sa); } /* test areawindow */ if(sa->win==0) { if(sa->winrct.yminwinrct.ymax) { openareawin(sa); set_func_space(sa); } } else { /* window te klein? */ if(sa->winrct.ymin==sa->winrct.ymax) closeareawin(sa); else { /* window veranderd? */ if(tempw.xmin!=sa->winrct.xmin || tempw.xmax!=sa->winrct.xmax || tempw.ymin!=sa->winrct.ymin || tempw.ymax!=sa->winrct.ymax) { addqueue(sa->win, CHANGED, 1); mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax); } } } sa= sa->next; } /* remake global windowarray */ bzero(areawinar, sizeof(void *)*MAXWIN); sa= G.curscreen->areabase.first; while(sa) { if(sa->headwin) areawinar[sa->headwin]= sa; if(sa->win) areawinar[sa->win]= sa; sa= sa->next; } /* test of winakt in orde is */ if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0; } ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se) { /* test of edge in area ligt, zo niet, vind een area die 'm wel heeft */ ScrEdge *se1=0, *se2=0, *se3=0, *se4=0; if(sa) { se1= findscredge(sa->v1, sa->v2); se2= findscredge(sa->v2, sa->v3); se3= findscredge(sa->v3, sa->v4); se4= findscredge(sa->v4, sa->v1); } if(se1!=se && se2!=se && se3!=se && se4!=se) { sa= G.curscreen->areabase.first; while(sa) { /* een beetje optimaliseren? */ if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) { se1= findscredge(sa->v1, sa->v2); se2= findscredge(sa->v2, sa->v3); se3= findscredge(sa->v3, sa->v4); se4= findscredge(sa->v4, sa->v1); if(se1==se || se2==se || se3==se || se4==se) return sa; } sa= sa->next; } } return sa; /* is keurig 0 als niet gevonden */ } ScrArea *closest_bigger_area() { ScrArea *sa, *big=0; float cent[3], vec[3],len, len1, len2, len3, dist=1000; short mval[2]; getmouseco_sc(mval); cent[0]= mval[0]; cent[1]= mval[1]; cent[2]= vec[2]= 0; sa= G.curscreen->areabase.first; while(sa) { if(sa!=curarea) { if(sa->winy>=curarea->winy) { /* mimimum van vier hoekpunten */ vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y; len= VecLenf(vec, cent); vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y; len1= VecLenf(vec, cent); vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y; len2= VecLenf(vec, cent); vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y; len3= VecLenf(vec, cent); len= MIN4(len, len1, len2, len3); /* plus centrum */ vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2; vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2; len+= 0.5*VecLenf(vec, cent); /* min afmeting */ len-= sa->winy+sa->winx; if(lennext; } if(big) return big; else return curarea; } /* ************ SCREENBEHEER ************** */ void test_scale_screen(bScreen *sc) /* testen of screenvertices vergroot/verkleind moeten worden */ /* testen of offset nog klopt */ { ScrVert *sv=0; ScrEdge *se; ScrArea *sa, *san; bScreen *old; int yval; float facx, facy, tempf, min[2], max[2]; sc->startx= prefstax; sc->starty= prefstay; sc->endx= prefstax+prefsizx-1; sc->endy= prefstay+prefsizy-1; /* calculate size */ sv= sc->vertbase.first; min[0]= min[1]= 0.0; max[0]= sc->sizex; max[1]= sc->sizey; while(sv) { min[0]= MIN2(min[0], sv->vec.x); min[1]= MIN2(min[1], sv->vec.y); max[0]= MAX2(max[0], sv->vec.x); max[1]= MAX2(max[1], sv->vec.y); sv= sv->next; } /* always make 0.0 left under */ sv= sc->vertbase.first; while(sv) { sv->vec.x -= min[0]; sv->vec.y -= min[1]; sv= sv->next; } sc->sizex= max[0]-min[0]; sc->sizey= max[1]-min[1]; if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) { facx= prefsizx; facx/= (float)sc->sizex; facy= prefsizy; facy/= (float)sc->sizey; /* make sure it fits! */ sv= sc->vertbase.first; while(sv) { tempf= ((float)sv->vec.x)*facx; sv->vec.x= (short)(tempf+0.5); sv->vec.x+= AREAGRID-1; sv->vec.x-= (sv->vec.x % AREAGRID); CLAMP(sv->vec.x, 0, prefsizx); tempf= ((float)sv->vec.y )*facy; sv->vec.y= (short)(tempf+0.5); sv->vec.y+= AREAGRID-1; sv->vec.y-= (sv->vec.y % AREAGRID); CLAMP(sv->vec.y, 0, prefsizy); sv= sv->next; } sc->sizex= prefsizx; sc->sizey= prefsizy; } /* test for collapsed areas. This could happen in some blender version... */ sa= sc->areabase.first; while(sa) { san= sa->next; if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) { del_area(sa); freeN(sa); remlink(&sc->areabase, sa); } sa= san; } /* make each window at least HEADERY high */ sa= sc->areabase.first; while(sa) { if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) { /* lower edge */ se= findscredge_sc(sc, sa->v4, sa->v1); if(se && sa->v1!=sa->v2 ) { select_connected_scredge(sc, se); /* all selected vertices get the right offset */ yval= sa->v2->vec.y-HEADERY; sv= sc->vertbase.first; while(sv) { /* if is a collapsed area */ if(sv!=sa->v2 && sv!=sa->v3) { if(sv->flag) sv->vec.y= yval; } sv= sv->next; } } } sa= sa->next; } } void redraw1func() { qenter(REDRAW, 1); if(G.f & G_DEBUG) printf("redrawfunc\n"); } void redraw2func() { qenter(REDRAW, 2); } void visiblefunc(int dummy) { if (G.curscreen) { if(glutGetWindow()==G.curscreen->mainwin) visible= dummy; } } void inputchangefunc(int state) { int win; if(state) { #ifdef WIN32 qenter(INPUTCHANGE, glutGetActiveWindow()); #else qenter(INPUTCHANGE, glutGetWindow()); #endif } if(G.f & G_DEBUG) printf("inputchangefunc %d %d\n", state, glutGetWindow()); } void reshapefunc(int x, int y) { bScreen *sc; int wx, wy, orx, ory; /* alleen voor hoofdwindow */ if(G.curscreen==0) return; if(G.f & G_DEBUG) printf("reshapefunc\n"); /* qenter(RESHAPE, mainwin); */ qenter(REDRAW, mainwin); init_my_mainwin(mainwin); wx= glutGet(GLUT_WINDOW_WIDTH); wy= glutGet(GLUT_WINDOW_HEIGHT); orx= glutGet(GLUT_WINDOW_X); ory= displaysizey -wy- glutGet(GLUT_WINDOW_Y); /* Minimizing on windows causes glut to set the * size to 0, which means things go bonkers */ if (wx == 0 || wy == 0) return; prefstax= orx; prefstay= ory; prefsizx= wx; prefsizy= wy; sc= G.main->screen.first; while(sc) { test_scale_screen(sc); sc= sc->id.next; } testareas(); } static int mymdown= 0; void mousefunc(int button, int state, int x, int y) { int but; if(button==GLUT_LEFT_BUTTON) { but= LEFTMOUSE; if(U.flag & TWOBUTTONMOUSE) { if(G.qual & LR_ALTKEY) but= MIDDLEMOUSE; } if(state==GLUT_DOWN) qenter(but, 1); else qenter(but, 0); #ifdef __WIN32 R.winpop= 1; #endif } else if(button==GLUT_MIDDLE_BUTTON) { if(state==GLUT_DOWN) mymdown= 1; else mymdown= 0; if(state==GLUT_DOWN) qenter(MIDDLEMOUSE, 1); else qenter(MIDDLEMOUSE, 0); } else if(button==GLUT_RIGHT_BUTTON) { if(state==GLUT_DOWN) qenter(RIGHTMOUSE, 1); else qenter(RIGHTMOUSE, 0); } } void mousemovefunc(int x, int y) { /* ommappen */ scrmousex= x; scrmousey= prefsizy-y; qenter(MOUSEX, scrmousex); /* (een te veel?) */ qenter(MOUSEY, scrmousey); } void rawkeyfunc(int key, int val, int y) { #ifdef __BeOS key= rawkey_beos(key); #endif #if !defined __BeOS && !defined WIN32 key= rawkey_x11(key); #endif #ifdef WIN32 /* really silly: windows repeats rawkeys! */ if (key==212 || key==213 || key==216) { static int lastval=-1, lastkey=-1; if(lastkey==key && lastval==val) return; lastval= val; lastkey= key; } #endif if(G.f & G_DEBUG) PRINT3(d, d, d, key & 255, val, y); qenter(key, val); } void keyboardfunc(uchar key, int x, int y) { if(G.f & G_DEBUG) printf("keyboardfunc: %c %d\n", key, key); qenter(KEYBD, key); } void do_the_glut_funcs() { glutKeyboardFunc(keyboardfunc); glutSpecialFunc(rawkeyfunc); glutMouseFunc(mousefunc); glutMotionFunc(mousemovefunc); glutPassiveMotionFunc(mousemovefunc); glutVisibilityFunc(visiblefunc); glutEntryFunc(inputchangefunc); } int mywinopen(int mode, short posx, short posy, short sizex, short sizey) { int win; glutInitDisplayMode(mode); glutInitWindowSize(sizex, sizey); glutInitWindowPosition(posx, displaysizey - sizey - posy); win= glutCreateWindow("Blender"); if(win==1) { glutDisplayFunc(redraw1func); glutReshapeFunc(reshapefunc); } else { glutDisplayFunc(redraw2func); } /* WARN! geen standaard fie */ if (borderless) glutNoBorder(); /* WARN! geen standaard fie */ glutDoWorkList(); #ifdef WIN32 if (win==1 && fullscreen) glutFullScreen(); #endif /* niet netjes: alleen eerste keer! */ if(win==1) init_my_mainwin(win); /* anders matrices in de war */ mywinset(win); glMatrixMode(GL_PROJECTION); glLoadIdentity(); ortho2(-0.5, (float)sizex-0.5, -0.5, (float)sizey-0.5); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return win; } bScreen *addscreen(char *name) /* gebruik de setprefsize() als je anders dan fullscreen wilt */ { /* deze functie zet de variabele G.curscreen * omdat alle hulpfuncties moeten weten welk screen */ bScreen *sc; ScrVert *sv1, *sv2, *sv3, *sv4; ScrEdge *se; ScrArea *sa; short startx, starty, endx, endy; sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name); if(prefsizx) { startx= prefstax; starty= prefstay; endx= prefstax+prefsizx-1; endy= prefstay+prefsizy-1; } else { prefstax= startx= 0; prefstay= starty= 0; endx= displaysizex-1; endy= displaysizey-1; prefsizx= displaysizex; prefsizy= displaysizey; } sc->startx= startx; sc->starty= starty; sc->endx= endx; sc->endy= endy; sc->sizex= sc->endx-sc->startx+1; sc->sizey= sc->endy-sc->starty+1; sc->scene= G.scene; if(mainwin==0) { sc->mainwin=mainwin= mywinopen(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH, sc->startx, sc->starty, sc->sizex, sc->sizey); do_the_glut_funcs(); glutIdleFunc(screenmain); /* glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX); */ glDrawBuffer(GL_FRONT); glClearColor(.45, .45, .45, 0.0); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffer(GL_BACK); warp_pointer(sc->sizex/2, sc->sizey/2); scrmousex= sc->sizex/2; scrmousey= sc->sizey/2; qenter(REDRAW, 1); } else sc->mainwin= mainwin; sv1= addscrvert(&sc->vertbase, 0, 0); sv2= addscrvert(&sc->vertbase, 0, sc->endy-sc->starty); sv3= addscrvert(&sc->vertbase, sc->sizex-1, sc->sizey-1); sv4= addscrvert(&sc->vertbase, sc->sizex-1, 0); se= addscredge(&sc->edgebase, sv1, sv2); se= addscredge(&sc->edgebase, sv2, sv3); se= addscredge(&sc->edgebase, sv3, sv4); se= addscredge(&sc->edgebase, sv4, sv1); sa= addscrarea(&sc->areabase, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY); G.curscreen= sc; return sc; } /* niet screen zelf vrijgeven */ void free_screen(bScreen *sc) { ScrArea *sa=0; freelistN(&sc->vertbase); freelistN(&sc->edgebase); sa= sc->areabase.first; while(sa) { del_area(sa); if(sa==curarea) curarea= 0; sa= sa->next; } freelistN(&sc->areabase); if(G.curscreen==sc) { G.curscreen= 0; winqueue_break= 1; /* overal uit queue's gaan */ } } void setscreen(bScreen *sc) { bScreen *sc1; ScrArea *sa; bWindow *win; int firstwin= 0; short mval[2]; if(sc->full) { /* vind de bijhorende full */ sc1= G.main->screen.first; while(sc1) { sa= sc1->areabase.first; if(sa->full==sc) { sc= sc1; break; } sc1= sc1->id.next; } if(sc1==0) printf("setscreen error\n"); } /* G.curscreen de-activeren */ if(G.curscreen && G.curscreen!=sc) { sa= G.curscreen->areabase.first; while(sa) { if(sa->win) winclose(sa->win); sa->win= 0; if(sa->headwin) winclose(sa->headwin); sa->headwin= 0; sa->hq= sa->headqueue; /* queue leeg */ sa->wq= sa->winqueue; uiFreeBlocks(&sa->uiblocks); sa= sa->next; } } if(G.curscreen != sc) { mywinset(sc->mainwin); } G.curscreen= sc; G.scene= sc->scene; countall(); /* recalculate winakt */ getmouseco_sc(mval); testareas(); G.curscreen->winakt= 0; win= swindowbase.first; while(win) { if(firstwin==0) firstwin= win->id; if(mval[0]>=win->xmin-1 && mval[0]<=win->xmax+2) { if(mval[1]>=win->ymin-1 && mval[1]<=win->ymax+2) { G.curscreen->winakt= win->id; break; } } win= win->next; } /* als buhv cursor op edge staat */ if(G.curscreen->winakt==0) G.curscreen->winakt= firstwin; areawinset(G.curscreen->winakt); /* zet curarea */ qenter(DRAWEDGES, 1); dodrawscreen= 1; /* patch! even gets lost,,,? */ winqueue_break= 1; /* overal uit de queue's gaan */ curedge= 0; /* global voor move en join */ } void area_fullscreen() /* met curarea */ { /* deze funktie toggelt: als area full is wordt de parent weer zichtbaar */ bScreen *sc, *oldscreen; ScrArea *newa, *old; if(curarea->full) { sc= curarea->full; /* de oude screen */ sc->full= 0; /* vind oude area */ old= sc->areabase.first; while(old) { if(old->full) break; old= old->next; } if(old==0) {error("something wrong in areafullscreen"); return;} copy_areadata(old, curarea); old->full= 0; free_libblock(&G.main->screen, G.curscreen); setscreen(sc); } else { /* is er maar 1 area? */ if(G.curscreen->areabase.first==G.curscreen->areabase.last) return; if(curarea->spacetype==SPACE_INFO) return; G.curscreen->full= 1; old= curarea; oldscreen= G.curscreen; sc= addscreen("temp"); /* deze zet G.curscreen */ splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99); newa= sc->areabase.first; newspace(newa->next, SPACE_INFO); curarea= old; G.curscreen= oldscreen; /* moet voor setscreen */ /* area kopieeren */ copy_areadata(newa, curarea); curarea->full= oldscreen; newa->full= oldscreen; newa->next->full= oldscreen; setscreen(sc); wich_cursor(newa); } } void copy_screen(bScreen *to, bScreen *from) { ScrVert *s1, *s2; ScrEdge *se; ScrArea *sa; ListBase lbase; /* alles van to vrijgeven */ free_screen(to); duplicatelist(&to->vertbase, &from->vertbase); duplicatelist(&to->edgebase, &from->edgebase); duplicatelist(&to->areabase, &from->areabase); s1= from->vertbase.first; s2= to->vertbase.first; while(s1) { s1->newv= s2; s2= s2->next; s1= s1->next; } se= to->edgebase.first; while(se) { se->v1= se->v1->newv; se->v2= se->v2->newv; sortscrvert(&(se->v1), &(se->v2)); se= se->next; } sa= to->areabase.first; while(sa) { sa->v1= sa->v1->newv; sa->v2= sa->v2->newv; sa->v3= sa->v3->newv; sa->v4= sa->v4->newv; sa->win= 0; sa->headwin= 0; sa->headqueue= sa->hq= 0; sa->winqueue= sa->wq= 0; sa->uiblocks.first= sa->uiblocks.last= NULL; duplicatespacelist(&lbase, &sa->spacedata); sa->spacedata= lbase; sa= sa->next; } /* op nul zetten (nodig?) */ s1= from->vertbase.first; while(s1) { s1->newv= 0; s1= s1->next; } } void duplicate_screen() { bScreen *sc, *oldscreen; if(G.curscreen->full) return; /* nieuw screen maken: */ oldscreen= G.curscreen; sc= addscreen(oldscreen->id.name+2); /* deze zet G.curscreen */ copy_screen(sc, oldscreen); G.curscreen= oldscreen; setscreen(sc); } /* ************ END SCREENBEHEER ************** */ /* ************ JOIN/SPLIT/MOVE ************** */ void joinarea(ScrArea *sa) { ScrArea *sa2, *san; ScrArea *up=0, *down=0, *right=0, *left=0; ScrEdge *setest; short val=0; char str[64]; /* welke edge? */ if(curedge==0) return; /* zit edge in area? of anders: welke area */ sa= test_edge_area(sa, curedge); if(sa==0) return; /* welke edges kunnen ermee? */ /* vind richtingen met zelfde edge */ sa2= G.curscreen->areabase.first; while(sa2) { if(sa2 != sa) { setest= findscredge(sa2->v1, sa2->v2); if(curedge==setest) right= sa2; setest= findscredge(sa2->v2, sa2->v3); if(curedge==setest) down= sa2; setest= findscredge(sa2->v3, sa2->v4); if(curedge==setest) left= sa2; setest= findscredge(sa2->v4, sa2->v1); if(curedge==setest) up= sa2; } sa2= sa2->next; } sa2= 0; setest= 0; if(left) val++; if(up) val++; if(right) val++; if(down) val++; if(val==0) return; else if(val==1) { if(left) sa2= left; else if(up) sa2= up; else if(right) sa2= right; else if(down) sa2= down; } if(sa2) { /* nieuwe area is oude sa */ if(sa2==left) { sa->v1= sa2->v1; sa->v2= sa2->v2; addscredge(&G.curscreen->edgebase, sa->v2, sa->v3); addscredge(&G.curscreen->edgebase, sa->v1, sa->v4); } else if(sa2==up) { sa->v2= sa2->v2; sa->v3= sa2->v3; addscredge(&G.curscreen->edgebase, sa->v1, sa->v2); addscredge(&G.curscreen->edgebase, sa->v3, sa->v4); } else if(sa2==right) { sa->v3= sa2->v3; sa->v4= sa2->v4; addscredge(&G.curscreen->edgebase, sa->v2, sa->v3); addscredge(&G.curscreen->edgebase, sa->v1, sa->v4); } else if(sa2==down) { sa->v1= sa2->v1; sa->v4= sa2->v4; addscredge(&G.curscreen->edgebase, sa->v1, sa->v2); addscredge(&G.curscreen->edgebase, sa->v3, sa->v4); } /* edge en area weg */ /* remlink(&G.curscreen->edgebase, setest); */ /* freeN(setest); */ del_area(sa2); remlink(&G.curscreen->areabase, sa2); if(curarea==sa2) curarea=0; freeN(sa2); removedouble_scredges(); removenotused_scredges(); removenotused_scrverts(); /* moet als laatste */ testareas(); qenter(DRAWEDGES, 1); /* test cursor en inputwindow */ qenter(MOUSEY, -1); } } short testsplitpoint(ScrArea *sa, char dir, float fac) /* return 0: geen split mogelijk */ /* else return (integer) screencoordinaat splitpunt */ { short val, x, y; /* area groot genoeg? */ val= 0; if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0; if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0; /* voor zekerheid */ if(fac<0.0) fac= 0.0; if(fac>1.0) fac= 1.0; if(dir=='h') { y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y); if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY+EDGEWIDTH2) y= sa->v2->vec.y- HEADERY-EDGEWIDTH2; else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY+EDGEWIDTH2) y= sa->v1->vec.y+ HEADERY+EDGEWIDTH2; else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY; else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY; else y-= (y % AREAGRID); return y; } else { x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x); if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX; else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX; else x-= (x % AREAGRID); return x; } } void splitarea(ScrArea *sa, char dir, float fac) { bScreen *sc; ScrArea *newa; ScrVert *sv1, *sv2; short split; if(sa==0) return; split= testsplitpoint(sa, dir, fac); if(split==0) return; sc= G.curscreen; areawinset(sa->win); if(dir=='h') { /* nieuwe vertices */ sv1= addscrvert(&sc->vertbase, sa->v1->vec.x, split); sv2= addscrvert(&sc->vertbase, sa->v4->vec.x, split); /* nieuwe edges */ addscredge(&sc->edgebase, sa->v1, sv1); addscredge(&sc->edgebase, sv1, sa->v2); addscredge(&sc->edgebase, sa->v3, sv2); addscredge(&sc->edgebase, sv2, sa->v4); addscredge(&sc->edgebase, sv1, sv2); /* nieuwe areas: boven */ newa= addscrarea(&sc->areabase, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype); copy_areadata(newa, sa); /* area onder */ sa->v2= sv1; sa->v3= sv2; } else { /* nieuwe vertices */ sv1= addscrvert(&sc->vertbase, split, sa->v1->vec.y); sv2= addscrvert(&sc->vertbase, split, sa->v2->vec.y); /* nieuwe edges */ addscredge(&sc->edgebase, sa->v1, sv1); addscredge(&sc->edgebase, sv1, sa->v4); addscredge(&sc->edgebase, sa->v2, sv2); addscredge(&sc->edgebase, sv2, sa->v3); addscredge(&sc->edgebase, sv1, sv2); /* nieuwe areas: links */ newa= addscrarea(&sc->areabase, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype); copy_areadata(newa, sa); /* area rechts */ sa->v1= sv1; sa->v2= sv2; } /* dubbele vertices en edges verwijderen */ removedouble_scrverts(); removedouble_scredges(); removenotused_scredges(); qenter(DRAWEDGES, 1); dodrawscreen= 1; /* patch! even gets lost,,,? */ testareas(); } void editsplitpoint() { ScrArea *sa; float fac; ushort event; short ok= 0, val, split, mval[2], mvalo[2]={-1010, -1010}, col[3]; char dir; sa= test_edge_area(curarea, curedge); if(sa==0) return; if(sa->win==0) return; if(sa->full) return; if(curedge==0) return; if(curedge->v1->vec.x==curedge->v2->vec.x) dir= 'h'; else dir= 'v'; mywinset(G.curscreen->mainwin); glDrawBuffer(GL_FRONT); /* hoort al goede matrix te hebben */ /* rekening houden met grid en minsize */ while(ok==0) { getmouseco_sc(mval); if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { mvalo[0]= mval[0]; mvalo[1]= mval[1]; if(dir=='h') { fac= mval[1]- (sa->v1->vec.y); fac/= sa->v2->vec.y- sa->v1->vec.y; } else { fac= mval[0]- sa->v1->vec.x; fac/= sa->v4->vec.x- sa->v1->vec.x; } split= testsplitpoint(sa, dir, fac); if(split==0) { ok= -1; } else { if(dir=='h') { sdrawXORline4(0, sa->totrct.xmin, split, sa->totrct.xmax, split); sdrawXORline4(1, sa->totrct.xmin, -1+split, sa->totrct.xmax, -1+split); } else { sdrawXORline4(0, split, sa->totrct.ymin, split, sa->totrct.ymax); sdrawXORline4(1, -1+split, sa->totrct.ymin, -1+split, sa->totrct.ymax); } } } event= extern_qread(&val); if(val && event==LEFTMOUSE) { if(dir=='h') { fac= split- (sa->v1->vec.y); fac/= sa->v2->vec.y- sa->v1->vec.y; } else { fac= split- sa->v1->vec.x; fac/= sa->v4->vec.x- sa->v1->vec.x; } ok= 1; } if(val && event==ESCKEY) { ok= -1; } } sdrawXORline4(-1, 0, 0, 0, 0); glDrawBuffer(GL_BACK); if(ok==1) { splitarea(sa, dir, fac); qenter(DRAWEDGES, 1); dodrawscreen= 1; /* patch! even gets lost,,,? */ } } void select_connected_scredge(bScreen *sc, ScrEdge *edge) { ScrEdge *se; ScrVert *sv; int oneselected; char dir; /* select connected, alleen in de juiste richting */ /* 'dir' is de richting van de EDGE */ if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v'; else dir= 'h'; sv= sc->vertbase.first; while(sv) { sv->flag= 0; sv= sv->next; } edge->v1->flag= 1; edge->v2->flag= 1; oneselected= 1; while(oneselected) { se= sc->edgebase.first; oneselected= 0; while(se) { if(se->v1->flag + se->v2->flag==1) { if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) { se->v1->flag= se->v2->flag= 1; oneselected= 1; } if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) { se->v1->flag= se->v2->flag= 1; oneselected= 1; } } se= se->next; } } } void moveareas() { ScrEdge *se; ScrVert *v1; ScrArea *sa; vec2s addvec; float PdistVL2Dfl(), vec1[2], vec2[2], vec3[2]; int dist, mindist= 1<<30; ushort event=0; short val, split, mval[2], mvalo[2]; short tel, x1, x2, y1, y2, bigger, smaller, headery, areaminy, col[3]; char dir; if(curarea->full) return; if(curedge==0 || curedge->border) return; if(curedge->v1->vec.x==curedge->v2->vec.x) dir= 'v'; else dir= 'h'; select_connected_scredge(G.curscreen, curedge); /* nu zijn alle vertices met 'flag==1' degene die verplaatst kunnen worden. */ /* we lopen de areas af en testen vrije ruimte met MINSIZE */ bigger= smaller= 10000; sa= G.curscreen->areabase.first; while(sa) { if(dir=='h') { /* als top of down edge select, test hoogte */ if(sa->headertype) { headery= HEADERY; areaminy= AREAMINY; } else { headery= 0; areaminy= EDGEWIDTH; } if(sa->v1->flag && sa->v4->flag) { if(sa->v2->vec.y==G.curscreen->sizey-1) /* bovenste edge */ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH; else y1= sa->v2->vec.y - sa->v1->vec.y-areaminy; if(y1v2->flag && sa->v3->flag) { if(sa->v1->vec.y==0) /* onderste edge */ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH; else y1= sa->v2->vec.y - sa->v1->vec.y-areaminy; if(y1v1->flag && sa->v2->flag) { x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX; if(x1v3->flag && sa->v4->flag) { x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX; if(x1next; } mywinset(G.curscreen->mainwin); glDrawBuffer(GL_FRONT); getmouseco_sc(mvalo); addvec.x= 0; addvec.y= 0; while(get_mbut() & L_MOUSE) { getmouseco_sc(mval); if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { if(dir=='h') { addvec.y+= mval[1]-mvalo[1]; if(addvec.y>bigger) addvec.y= bigger; if(addvec.y<-smaller) addvec.y= -smaller; } else { addvec.x+= mval[0]-mvalo[0]; if(addvec.x>bigger) addvec.x= bigger; if(addvec.x<-smaller) addvec.x= -smaller; } mvalo[0]= mval[0]; mvalo[1]= mval[1]; tel= 0; se= G.curscreen->edgebase.first; while(se) { if(se->v1->flag && se->v2->flag) { /* met areagrid even behelpen, verderop is OK! */ x1= se->v1->vec.x+addvec.x-(addvec.x % AREAGRID); x2= se->v2->vec.x+addvec.x-(addvec.x % AREAGRID); y1= se->v1->vec.y+addvec.y-(addvec.y % AREAGRID); y2= se->v2->vec.y+addvec.y-(addvec.y % AREAGRID); sdrawXORline4(tel++, x1, y1, x2, y2); sdrawXORline4(tel++, x1+1, y1+1, x2+1, y2+1); tel &= 3; } se= se->next; } } else usleep(2); event= extern_qread(&val); if(val) { if(event==ESCKEY) break; if(event==LEFTMOUSE) break; if(event==SPACEKEY) break; } } /* wissen */ sdrawXORline4(-1, 0, 0, 0, 0); v1= G.curscreen->vertbase.first; while(v1) { if(v1->flag && event!=ESCKEY) { /* zo is AREAGRID netjes */ if(addvec.x && v1->vec.x>0 && v1->vec.xsizex-1) { v1->vec.x+= addvec.x; if(addvec.x != bigger && addvec.x != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID); } if(addvec.y && v1->vec.y>0 && v1->vec.ysizey-1) { v1->vec.y+= addvec.y; /* with these lines commented out you can pull the top bar exact to the screen border. */ /* if(addvec.y != bigger && addvec.y != -smaller) { */ v1->vec.y+= AREAGRID-1; v1->vec.y-= (v1->vec.y % AREAGRID); /* } */ } } v1->flag= 0; v1= v1->next; } if(event!=ESCKEY) { removedouble_scrverts(); removedouble_scredges(); testareas(); } glDrawBuffer(GL_BACK); qenter(DRAWEDGES, 1); dodrawscreen= 1; /* patch! even gets lost,,,? */ } void scrollheader() { short mval[2], mvalo[2]; if(curarea->headbutlenwinx) { curarea->headbutofs= 0; } else if(curarea->headbutofs+curarea->winx > curarea->headbutlen) { curarea->headbutofs= curarea->headbutlen-curarea->winx; } getmouseco_sc(mvalo); while(get_mbut() & M_MOUSE) { getmouseco_sc(mval); if(mval[0]!=mvalo[0]) { curarea->headbutofs-= (mval[0]-mvalo[0]); if(curarea->headbutlen-curarea->winx < curarea->headbutofs) curarea->headbutofs= curarea->headbutlen-curarea->winx; if(curarea->headbutofs<0) curarea->headbutofs= 0; defheadchange(); if(curarea->headdraw) curarea->headdraw(); screen_swapbuffers(); mvalo[0]= mval[0]; } else usleep(2); } } int select_area(int spacetype) { /* vanuit editroutines aanroepen, als er meer area's * zijn van type 'spacetype' kan er een area aangegeven worden */ ScrArea *sa, *sact; bWindow *win; int tot=0; ushort event; short val, mval[2]; sa= G.curscreen->areabase.first; while(sa) { if(sa->spacetype==spacetype) { sact= sa; tot++; } sa= sa->next; } if(tot==0) { error("Can't do this! Open correct window"); return 0; } if(tot==1) { if(curarea!=sact) areawinset(sact->win); return 1; } else if(tot>1) { tempcursor(GLUT_CURSOR_HELP); while(1) { event= extern_qread(&val); if(val) { if(event==ESCKEY) break; if(event==LEFTMOUSE) break; if(event==SPACEKEY) break; } else usleep(1); } tempcursor(CURSOR_STD); /* recalculate winakt */ getmouseco_sc(mval); G.curscreen->winakt= 0; win= swindowbase.first; while(win) { if(mval[0]>=win->xmin-1 && mval[0]<=win->xmax+2) { if(mval[1]>=win->ymin-1 && mval[1]<=win->ymax+2) { G.curscreen->winakt= win->id; break; } } win= win->next; } if(event==LEFTMOUSE) { sa= areawinar[G.curscreen->winakt]; if(sa->spacetype==spacetype) areawinset(G.curscreen->winakt); else { error("wrong window"); return 0; } } } if(event==LEFTMOUSE) return 1; else return 0; } /* ************ END JOIN/SPLIT/MOVE ************** */ /* **************** DRAW SCREENEDGES ***************** */ #define EDGE_EXTEND 3 void drawedge(short x1, short y1, short x2, short y2) { int a, dir; vec2f v1, v2; v1.x= x1; v1.y= y1; v2.x= x2; v2.y= y2; if(v1.x== v2.x) { /* vertikaal */ dir= v1.y-v2.y; if(dir>0) dir= 1; else dir= -1; if (dir==-1) { if (v1.y==0) v1.y-= EDGE_EXTEND; if (v2.y==G.curscreen->sizey) v2.y+= EDGE_EXTEND; } else { if (v2.y==0) v2.y-= EDGE_EXTEND; if (v1.y==G.curscreen->sizey) v1.y+= EDGE_EXTEND; } v1.y-= dir*EDGEWIDTH2; v2.y+= dir*EDGEWIDTH2; v1.x+= EDGEWIDTH2; v2.x+= EDGEWIDTH2; for(a=0; a0) dir= 1; else dir= -1; if (dir==-1) { if (v1.x==0) v1.x-= EDGE_EXTEND; if (v2.x==G.curscreen->sizex) v2.x+= EDGE_EXTEND; } else { if (v2.x==0) v2.x-= EDGE_EXTEND; if (v1.x==G.curscreen->sizex) v1.x+= EDGE_EXTEND; } v1.x-= dir*EDGEWIDTH2; v2.x+= dir*EDGEWIDTH2; v1.y-= EDGEWIDTH2; v2.y-= EDGEWIDTH2; for(a=0; av1->vec); v2= &(se->v2->vec); /* borders screen niet tekenen */ /* vanwege resolutie verschillen (PC/SGI files) de linit een * beetje afronden? */ se->border= 1; if(v1->x<=1 && v2->x<=1) return; if(v1->x>=sc->sizex-2 && v2->x>=sc->sizex-2) return; if(v1->y<=1 && v2->y<=1) return; if(v1->y>=sc->sizey-2 && v2->y>=sc->sizey-2) return; se->border= 0; drawedge(v1->x, v1->y, v2->x, v2->y); } void drawscreen() { ScrEdge *se; mywinset(G.curscreen->mainwin); ortho2(-0.5, (float)G.curscreen->sizex-0.5, -0.5, (float)G.curscreen->sizey-0.5); /* two times, because there is no 'win_swap' for this available */ glDrawBuffer(GL_FRONT); se= G.curscreen->edgebase.first; while(se) { drawscredge(se); se= se->next; } glDrawBuffer(GL_BACK); se= G.curscreen->edgebase.first; while(se) { drawscredge(se); se= se->next; } } /* ********************************* */ bScreen *default_foursplit() { bScreen *sc; ScrArea *sa; View3D *vd; int tel; sc= addscreen("screen"); splitarea( (ScrArea *)sc->areabase.first, 'h', 0.25); splitarea( (ScrArea *)sc->areabase.last, 'h', 0.49); splitarea( (ScrArea *)sc->areabase.last, 'h', 0.99); sa= sc->areabase.last; newspace(sa, SPACE_INFO); /* sa->headertype= NOHEADER; */ /* alle nieuwe areas komen op einde lijst! */ sa= sc->areabase.first; splitarea( sa->next, 'v', 0.5); sa= sc->areabase.first; splitarea( sa->next, 'v', 0.5); sa= sc->areabase.first; sa->headertype= HEADERTOP; newspace(sa, SPACE_BUTS); sa= sa->next; /* zet de view3d's en geef ze de juiste aanzicht */ tel= 1; while(sa) { if(sa->spacetype==0) { newspace(sa, SPACE_VIEW3D); vd= sa->spacedata.first; vd->persp= 0; if(tel==1) { vd->view= 1; vd->viewquat[0]= fcos(M_PI/4.0); vd->viewquat[1]= -fsin(M_PI/4.0); } else if(tel==2) { vd->view= 3; vd->viewquat[0]= 0.5; vd->viewquat[1]= -0.5; vd->viewquat[2]= -0.5; vd->viewquat[3]= -0.5; } else if(tel==3) { vd->view= 7; } else vd->persp= 1; tel++; } sa= sa->next; } testareas(); return sc; } bScreen *default_twosplit() { bScreen *sc; ScrArea *sa; sc= addscreen("screen"); splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99); sa= sc->areabase.first; newspace(sa, SPACE_VIEW3D); newspace(sa->next, SPACE_INFO); return sc; } void initscreen() { /* opent en initialiseert */ getdisplaysize(); default_twosplit(); }