4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 * All screen functions that are related to the interface
32 * handling and drawing. Might be split up as well later...
43 #include <ctype.h> /* isprint */
47 #include "MEM_guardedalloc.h"
53 #include "BLI_blenlib.h"
54 #include "BLI_arithb.h"
56 #include "IMB_imbuf_types.h"
57 #include "IMB_imbuf.h"
59 #include "DNA_action_types.h"
60 #include "DNA_object_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_space_types.h"
63 #include "DNA_sound_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_userdef_types.h"
67 #include "BLO_writefile.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_global.h"
71 #include "BKE_library.h"
73 #include "BKE_blender.h"
74 #include "BKE_screen.h"
76 #include "BIF_editsound.h"
77 #include "BIF_glutil.h"
79 #include "BIF_graphics.h"
80 #include "BIF_interface.h"
81 #include "BIF_mainqueue.h"
82 #include "BIF_mywindow.h"
83 #include "BIF_renderwin.h"
84 #include "BIF_screen.h"
85 #include "BIF_space.h"
86 #include "BIF_toets.h"
87 #include "BIF_toolbox.h"
88 #include "BIF_usiblender.h"
89 #include "BIF_keyval.h"
90 #include "BIF_resources.h"
93 #include "BSE_filesel.h"
94 #include "BSE_headerbuttons.h"
95 #include "BSE_seqaudio.h"
98 #include "BPY_extern.h"
101 #include "render.h" /* R.flag */
107 * - WATCH THE EDGES, VERTICES HAVE TO BE IN ORDER...
108 (lowest pointer first). Otherwise unpredictable effects!
109 * - problem: flags here are not nicely implemented. After usage
110 always reset to zero.
113 /* comment added to test orange branch */
115 static void testareas(void);
116 static void area_autoplayscreen(void);
117 static void wait_for_event(void);
120 /* ********* Globals *********** */
122 static Window *mainwin= NULL;
123 static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
124 static short dodrawscreen= 1;
125 static ScrArea *areawinar[MAXWIN];
126 static ScrArea *g_activearea= NULL;
127 short winqueue_break= 0;
130 /* prototypes -------------------*/
131 int afterqtest(short win, unsigned short evt);
132 unsigned short screen_qread(short *val, char *ascii);
133 void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii);
134 static void drawscredge_area(ScrArea *sa);
136 /**********************************************************************/
138 extern int textediting;
140 static void screen_set_cursor(bScreen *sc)
143 ScrArea *sa= areawinar[sc->winakt];
145 set_cursor(sa->cursor);
147 set_cursor(CURSOR_STD);
151 void waitcursor(int val)
154 set_cursor(CURSOR_WAIT);
156 screen_set_cursor(G.curscreen);
160 static int choose_cursor(ScrArea *sa)
162 if (sa->spacetype==SPACE_VIEW3D) {
163 if(G.obedit) return CURSOR_EDIT;
164 else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
165 else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
166 else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
167 else return CURSOR_STD;
173 void wich_cursor(ScrArea *sa)
175 sa->cursor= choose_cursor(sa);
177 screen_set_cursor(G.curscreen);
181 void setcursor_space(int spacetype, short cur)
186 for (sc= G.main->screen.first; sc; sc= sc->id.next)
187 for (sa= sc->areabase.first; sa; sa= sa->next)
188 if(sa->spacetype==spacetype)
191 screen_set_cursor(G.curscreen);
195 /* ********* IN/OUT ************* */
197 void getmouseco_sc(short *mval) /* screen coordinates */
202 /* mouse_cursor called during a script (via Window.QHandle) need
203 * this function for getmouseco_areawin to work: */
204 void set_g_activearea(ScrArea *sa)
206 if (sa) g_activearea = sa;
209 void getmouseco_areawin(short *mval) /* internal area coordinates */
213 if(g_activearea && g_activearea->win) {
214 mval[0]-= g_activearea->winrct.xmin;
215 mval[1]-= g_activearea->winrct.ymin;
219 void getmouseco_headwin(short *mval) /* internal area coordinates */
223 if(g_activearea && g_activearea->headwin) {
224 mval[0]-= g_activearea->headrct.xmin;
225 mval[1]-= g_activearea->headrct.ymin;
229 void headerprint(char *str)
231 if(curarea->headertype) {
232 areawinset(curarea->headwin);
236 BIF_ThemeColor(TH_MENU_TEXT); /* better than cpack(0x0) color no? (desoto) */
237 glRasterPos2i(20+curarea->headbutofs, 6);
238 BMF_DrawString(G.font, str);
240 curarea->head_swap= WIN_BACK_OK;
241 areawinset(curarea->win);
244 // dunno... thats for later (ton)
248 /* *********** STUFF ************** */
250 static int scredge_is_horizontal(ScrEdge *se)
252 return (se->v1->vec.y == se->v2->vec.y);
255 static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
259 for (se= sc->edgebase.first; se; se= se->next) {
260 if (scredge_is_horizontal(se)) {
262 min= MIN2(se->v1->vec.x, se->v2->vec.x);
263 max= MAX2(se->v1->vec.x, se->v2->vec.x);
265 if (abs(mval[1]-se->v1->vec.y)<=2 && mval[0] >= min && mval[0]<=max)
270 min= MIN2(se->v1->vec.y, se->v2->vec.y);
271 max= MAX2(se->v1->vec.y, se->v2->vec.y);
273 if (abs(mval[0]-se->v1->vec.x)<=2 && mval[1] >= min && mval[1]<=max)
281 void areawinset(short win)
284 curarea= areawinar[win];
286 printf("error in areawinar %d ,areawinset\n", win);
290 BIF_SetTheme(curarea);
292 switch(curarea->spacetype) {
294 G.vd= curarea->spacedata.first;
297 G.sipo= curarea->spacedata.first;
301 G.buts= curarea->spacedata.first;
305 SpaceSeq *sseq= curarea->spacedata.first;
310 G.soops= curarea->spacedata.first;
311 G.v2d= &G.soops->v2d;
314 G.sima= curarea->spacedata.first;
318 G.ssound= curarea->spacedata.first;
319 G.v2d= &G.ssound->v2d;
322 G.saction= curarea->spacedata.first;
323 G.v2d= &G.saction->v2d;
326 G.snla= curarea->spacedata.first;
331 SpaceTime *stime= curarea->spacedata.first;
340 if(win) mywinset(win);
343 #define SCR_BACK 0.55
346 void headerbox(ScrArea *area)
348 float width= area->winx;
351 glClearColor(SCR_BACK, SCR_BACK, SCR_BACK, 0.0);
352 glClear(GL_COLOR_BUFFER_BIT);
354 active= area_is_active_area(area);
356 if(active) BIF_ThemeColor(TH_HEADER);
357 else BIF_ThemeColor(TH_HEADERDESEL);
359 /* weird values here... is because of window matrix that centres buttons */
360 if(area->headertype==HEADERTOP) {
362 uiRoundBoxEmboss(-0.5+area->headbutofs, -10.0, width-1.5+area->headbutofs, HEADERY-2.0, SCR_ROUND, active);
366 uiRoundBoxEmboss(-0.5+area->headbutofs, -3.5, width-1.5+area->headbutofs, HEADERY+10, SCR_ROUND, active);
372 int area_is_active_area(ScrArea *area)
374 return (g_activearea && area==g_activearea);
377 void scrarea_do_headdraw(ScrArea *area)
379 if (area->headertype) {
380 areawinset(area->headwin);
384 /* we make scissor test slightly smaller not to destroy rounded headers */
385 glScissor(area->headrct.xmin+5, area->headrct.ymin, area->winx-10, HEADERY);
387 switch(area->spacetype) {
388 case SPACE_FILE: file_buttons(); break;
389 case SPACE_INFO: info_buttons(); break;
390 case SPACE_VIEW3D: view3d_buttons(); break;
391 case SPACE_IPO: ipo_buttons(); break;
392 case SPACE_BUTS: buts_buttons(); break;
393 case SPACE_SEQ: seq_buttons(); break;
394 case SPACE_IMAGE: image_buttons(); break;
395 case SPACE_IMASEL: imasel_buttons(); break;
396 case SPACE_OOPS: oops_buttons(); break;
397 case SPACE_TEXT: text_buttons(); break;
398 case SPACE_SCRIPT:script_buttons(); break;
399 case SPACE_SOUND: sound_buttons(); break;
400 case SPACE_ACTION: action_buttons(); break;
401 case SPACE_NLA: nla_buttons(); break;
402 case SPACE_TIME: time_buttons(area); break;
406 //glScissor(area->winrct.xmin, area->winrct.xmax, area->winx, area->winy);
407 area->head_swap= WIN_BACK_OK;
410 void scrarea_do_headchange(ScrArea *area)
412 float ofs= area->headbutofs;
414 if (area->headertype==HEADERDOWN) {
415 bwin_ortho2(area->headwin, -0.375+ofs, area->headrct.xmax-area->headrct.xmin-0.375+ofs, -3.375, area->headrct.ymax-area->headrct.ymin-3.375+1.0);
416 } else if (area->headertype==HEADERTOP) {
417 bwin_ortho2(area->headwin, -0.375+ofs, area->headrct.xmax-area->headrct.xmin-0.375+ofs, -2.375-1.0, area->headrct.ymax-area->headrct.ymin-2.375);
422 static void openheadwin(ScrArea *sa);
423 static void closeheadwin(ScrArea *sa);
425 static void scrarea_change_headertype(ScrArea *sa, int newtype)
427 sa->headertype= newtype;
431 uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
441 mainqenter(DRAWEDGES, 1);
445 static void headmenu(ScrArea *sa)
447 short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
450 scrarea_change_headertype(sa, val);
454 static void addqueue_ext(short win, unsigned short event, short val, char ascii)
456 if (win<4 || !areawinar[win]) {
457 if(win==0) // other win ids are for mainwin & renderwin
458 printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
466 bwin_qadd(win, &evt);
470 void addqueue(short win, unsigned short event, short val)
472 addqueue_ext(win, event, val, 0);
475 void scrarea_queue_winredraw(ScrArea *area)
477 addqueue(area->win, REDRAW, 1);
479 void scrarea_queue_headredraw(ScrArea *area)
481 if (area->headwin) addqueue(area->headwin, REDRAW, 1);
483 void scrarea_queue_redraw(ScrArea *area)
485 scrarea_queue_winredraw(area);
486 scrarea_queue_headredraw(area);
489 static void scrollheader(ScrArea *area);
490 static void scrarea_dispatch_header_events(ScrArea *sa)
494 short do_redraw=0, do_change=0;
496 areawinset(sa->headwin);
498 while(bwin_qread(sa->headwin, &evt)) {
500 if( uiDoBlocks(&curarea->uiblocks, evt.event)!=UI_NOTHING ) evt.event= 0;
504 do_headerbuttons(evt.val);
508 if (G.qual & LR_CTRLKEY) {
509 window_lower(mainwin);
511 window_raise(mainwin);
530 if (winqueue_break == 0) {
531 scrarea_do_winhandle(sa, &evt);
532 if (winqueue_break == 0) areawinset(sa->headwin);
536 if(winqueue_break) return;
540 /* test: does window still exist? */
541 tempsa= areawinar[sa->headwin];
542 if(tempsa==0) return;
544 /* this functional separation does not work as well as i expected... */
545 if(do_change) scrarea_do_headchange(sa);
546 if(do_redraw) scrarea_do_headdraw(sa);
549 static void scrarea_dispatch_events(ScrArea *sa)
553 short do_redraw=0, do_change=0;
555 if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
557 while(bwin_qread(sa->win, &evt)) {
558 if(evt.event==REDRAW) {
561 else if(evt.event==CHANGED) {
567 scrarea_do_winhandle(sa, &evt);
570 if(winqueue_break) return;
573 /* test: does window still exist */
574 tempsa= areawinar[sa->win];
575 if(tempsa==0) return;
577 if (do_change || do_redraw) {
580 scrarea_do_winchange(curarea);
582 scrarea_do_windraw(curarea);
592 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
594 scrarea_queue_winredraw(sa);
595 sa->win_swap &= ~WIN_FRONT_OK;
598 scrarea_queue_headredraw(sa);
599 sa->head_swap &= ~WIN_FRONT_OK;
605 void markdirty_all_back(void)
609 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
611 sa->win_swap &= ~WIN_BACK_OK;
614 sa->head_swap &= ~WIN_BACK_OK;
618 /* if needed; backbuffer selection redraw */
619 if(G.vd) G.vd->flag |= V3D_NEEDBACKBUFDRAW;
623 void markdirty_win_back(short winid)
625 ScrArea *sa= areawinar[winid];
627 if(sa->win==winid) sa->win_swap &= ~WIN_BACK_OK;
628 else sa->head_swap &= ~WIN_BACK_OK;
633 int is_allowed_to_change_screen(bScreen *new)
635 /* not when curscreen is full
636 * not when obedit && old->scene!=new->scene
640 if(G.curscreen->full != SCREENNORMAL) return 0;
641 if(curarea->full) return 0;
643 if(G.curscreen->scene!=new->scene) return 0;
648 void splash(void *data, int datasize, char *string)
650 extern void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
655 bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
659 mywinset(G.curscreen->mainwin);
666 maxy = MIN2(bbuf->y, 18);
668 for (y = 0; y < maxy; y++) {
669 for (x = 0; x < bbuf->x; x++) {
675 glDrawBuffer(GL_FRONT);
677 uiDrawBoxShadow(200, (prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2, (prefsizx+bbuf->x)/2, (prefsizy+bbuf->y)/2);
679 glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);
680 glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
686 if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
687 if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
690 width= BMF_GetStringWidth(font, string);
693 glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
694 BMF_DrawString(font, string);
698 glDrawBuffer(GL_BACK);
702 // flush input buffers ....
703 // this might break some things
706 BIF_wait_for_statechange();
716 mainqenter(DRAWEDGES, 1);
720 static void moveareas(ScrEdge *edge);
721 static void joinarea_interactive(ScrArea *area, ScrEdge *onedge);
722 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
724 static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val)
727 // don't allow users to edit full screens
728 if (actarea && actarea->full) {
732 if (evt==LEFTMOUSE) {
734 } else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
737 if (!actarea->headertype) {
738 edgeop= pupmenu("Split Area|Join Areas|Add Header");
740 edgeop= pupmenu("Split Area|Join Areas|No Header");
744 splitarea_interactive(actarea, actedge);
745 } else if (edgeop==2) {
746 joinarea_interactive(actarea, actedge);
747 } else if (edgeop==3) {
748 scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
751 else blenderqread(evt, val); // global hotkeys
757 extern void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
758 void test_scale_screen(bScreen *);
760 static void resize_screens(int x, int y, int w, int h) {
766 test_scale_screen(G.curscreen);
770 static void init_mainwin(void)
772 int orx, ory, sizex, sizey;
774 glEnable(GL_SCISSOR_TEST);
776 window_get_position(mainwin, &orx, &ory);
777 window_get_size(mainwin, &sizex, &sizey);
779 /* XXX, temporary stupid fix for minimize at windows */
780 if (!sizex && !sizey) {
784 mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
785 resize_screens(orx, ory, sizex, sizey);
790 static short afterqueue[MAXQUEUE][3];
791 static int nafterqitems= 0;
793 void addafterqueue(short win, unsigned short evt, short val)
795 if (nafterqitems<MAXQUEUE) {
796 afterqueue[nafterqitems][0]= win;
797 afterqueue[nafterqitems][1]= evt;
798 afterqueue[nafterqitems][2]= val;
803 static void append_afterqueue(void)
805 while (nafterqitems) {
806 short win= afterqueue[nafterqitems-1][0];
807 unsigned short evt= afterqueue[nafterqitems-1][1];
808 short val= afterqueue[nafterqitems-1][2];
810 addqueue(win, evt, val);
816 /* check for event in afterqueue, used in force_draw in space.c */
817 int afterqtest(short win, unsigned short evt)
821 for(a=0; a<nafterqitems; a++) {
822 if(afterqueue[a][0]==win && afterqueue[a][1]==evt) return 1;
828 static char ext_load_str[256]= {0, 0};
829 void add_readfile_event(char *filename)
831 mainqenter(LOAD_FILE, 1);
832 strcpy(ext_load_str, filename);
833 BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
836 static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
838 static void flush_extqd_events(void) {
839 if (ext_inputchange) {
840 mainqenter(INPUTCHANGE, ext_inputchange);
841 } else if (ext_reshape) {
842 mainqenter(RESHAPE, ext_redraw);
843 } else if (ext_redraw) {
844 mainqenter(REDRAW, ext_redraw);
845 } else if (ext_mousemove) {
848 getmouseco_sc(mouse);
850 mainqenter(MOUSEX, mouse[0]);
851 mainqenter(MOUSEY, mouse[1]);
854 ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
857 unsigned short qtest(void)
860 winlay_process_events(0);
866 /* return true if events are waiting anywhere */
871 if (nafterqitems || qtest()) return 1;
873 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
874 if (bwin_qtest(sa->win)) return 1;
875 if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
881 static void wait_for_event(void)
883 while (!mainqtest()) {
884 winlay_process_events(1);
888 unsigned short screen_qread(short *val, char *ascii)
890 unsigned short event;
894 event= mainqread(val, ascii);
896 if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
897 if(*val) G.qual |= LR_SHIFTKEY;
898 else G.qual &= ~LR_SHIFTKEY;
900 else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
901 if(*val) G.qual |= LR_ALTKEY;
902 else G.qual &= ~LR_ALTKEY;
904 else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
905 if(*val) G.qual |= LR_CTRLKEY;
906 else G.qual &= ~LR_CTRLKEY;
908 else if(event==COMMANDKEY) { // OSX
909 if(*val) G.qual |= LR_COMMANDKEY;
910 else G.qual &= ~LR_COMMANDKEY;
916 unsigned short extern_qread_ext(short *val, char *ascii)
918 /* stores last INPUTCHANGE and last REDRAW */
919 unsigned short event;
921 event= screen_qread(val, ascii);
922 if(event==RESHAPE) ext_reshape= *val;
923 else if(event==REDRAW) ext_redraw= *val;
924 else if(event==INPUTCHANGE) ext_inputchange= *val;
925 else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
926 else if((G.qual & (LR_CTRLKEY|LR_ALTKEY)) && event==F3KEY) {
927 if(*val) BIF_screendump(0);
932 unsigned short extern_qread(short *val)
935 return extern_qread_ext(val, &ascii);
938 int blender_test_break(void)
941 static double ltime= 0;
942 double curtime= PIL_check_seconds_timer();
944 /* only check for breaks every 10 milliseconds
945 * if we get called more often.
947 if ((curtime-ltime)>.001) {
952 if (extern_qread(&val) == ESCKEY) {
959 return (G.afbreek==1);
962 void reset_autosave(void) {
963 window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
966 /* ************ handlers ************** */
968 /* don't know yet how the handlers will evolve, for simplicity
969 i choose for an array with eventcodes, this saves in a file!
971 void add_screenhandler(bScreen *sc, short eventcode, short val)
976 for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
977 if( sc->handler[a]==eventcode ) {
978 sc->handler[a+1]= val;
981 else if( sc->handler[a]==0) {
982 sc->handler[a]= eventcode;
983 sc->handler[a+1]= val;
987 if(a==SCREEN_MAXHANDLER) printf("error; max (4) screen handlers reached!\n");
990 void rem_screenhandler(bScreen *sc, short eventcode)
994 for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
995 if( sc->handler[a]==eventcode) {
1002 int has_screenhandler(bScreen *sc, short eventcode)
1006 for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
1007 if( sc->handler[a]==eventcode) {
1014 static void animated_screen(bScreen *sc, short val)
1016 if (U.mixbufsize && (val & TIME_WITH_SEQ_AUDIO)) {
1020 audiostream_start( CFRA );
1023 int cfra = audiostream_pos();
1024 if(cfra <= CFRA) CFRA++;
1030 if(CFRA > EFRA) CFRA= SFRA;
1033 update_for_newframe_nodraw(1);
1035 if(val & TIME_ALL_3D_WIN)
1036 allqueue(REDRAWVIEW3D, 0);
1037 else if(val & TIME_LEFTMOST_3D_WIN) {
1038 ScrArea *sa= sc->areabase.first, *samin=NULL;
1040 for(; sa; sa= sa->next) {
1041 if(sa->spacetype==SPACE_VIEW3D) {
1042 if(sa->winrct.xmin - sa->winrct.ymin < min) {
1044 min= sa->winrct.xmin - sa->winrct.ymin;
1048 if(samin) scrarea_queue_winredraw(samin);
1050 if(val & TIME_ALL_ANIM_WIN) allqueue(REDRAWANIM, 0);
1051 if(val & TIME_ALL_BUTS_WIN) allqueue(REDRAWBUTSALL, 0);
1053 allqueue(REDRAWTIME, 0);
1056 /* because we still have to cope with subloops, this function is called
1057 in viewmove() for example too */
1059 /* returns 1 if something was handled */
1060 /* restricts to frames-per-second setting for frequency of updates */
1061 int do_screenhandlers(bScreen *sc)
1063 static double ltime=0.0;
1064 double swaptime, time;
1067 time = PIL_check_seconds_timer();
1068 swaptime= 1.0/(float)G.scene->r.frs_sec;
1070 /* only now do the handlers */
1071 if(swaptime < time-ltime || ltime==0.0) {
1075 for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
1076 switch(sc->handler[a]) {
1077 case SCREEN_HANDLER_ANIM:
1078 animated_screen(sc, sc->handler[a+1]);
1081 case SCREEN_HANDLER_PYTHON:
1084 case SCREEN_HANDLER_VERSE:
1090 else if( qtest()==0) PIL_sleep_ms(5); // 5 milliseconds pause, for idle
1092 /* separate check for if we need to add to afterqueue */
1093 /* is only to keep mainqueue awqke */
1094 for(a=0; a<SCREEN_MAXHANDLER; a+=2) {
1095 if(sc->handler[a]) {
1096 ScrArea *sa= sc->areabase.first;
1097 if(sa->headwin) addafterqueue(sa->headwin, SCREEN_HANDLER, 1);
1098 else addafterqueue(sa->win, SCREEN_HANDLER, 1);
1105 /* ****** end screen handlers ************ */
1107 static void drawscreen(void)
1111 mywinset(G.curscreen->mainwin);
1112 myortho2(-0.375, (float)G.curscreen->sizex-0.375, -0.375, (float)G.curscreen->sizey-0.375);
1114 sa= G.curscreen->areabase.first;
1116 drawscredge_area(sa);
1120 /* this double draw patch seems to be needed for certain sgi's (octane, indigo2) */
1121 #if defined(__sgi) || defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__)
1122 glDrawBuffer(GL_FRONT);
1124 sa= G.curscreen->areabase.first;
1126 drawscredge_area(sa);
1130 glDrawBuffer(GL_BACK);
1134 static void screen_dispatch_events(void) {
1135 int events_remaining= 1;
1138 window_make_active(mainwin); // added it here instead of screenmain (ton)
1140 while (events_remaining) {
1141 events_remaining= 0;
1144 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1145 /* first check header, then rest. Header sometimes has initialization code */
1146 if (sa->headwin && bwin_qtest(sa->headwin)) {
1147 scrarea_dispatch_header_events(sa);
1148 events_remaining= 1;
1150 if (winqueue_break) break;
1152 if (bwin_qtest(sa->win)) {
1153 scrarea_dispatch_events(sa);
1154 events_remaining= 1;
1156 if (winqueue_break) break;
1159 if (winqueue_break) break;
1167 screen_swapbuffers();
1168 do_screenhandlers(G.curscreen);
1171 static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval)
1175 /* hotspot area of 1 pixel extra */
1177 for (sa= sc->areabase.first; sa; sa= sa->next) {
1178 if( sa->totrct.xmin + 1 < mval[0] )
1179 if( sa->totrct.ymin + 1 < mval[1] )
1180 if( sa->totrct.xmax - 1 > mval[0] )
1181 if( sa->totrct.ymax - 1 > mval[1] )
1187 /* ugly yah, will disappear on better event system */
1188 /* is called from interface.c after button events */
1189 static char delayed_undo_name[64];
1190 void screen_delayed_undo_push(char *name)
1192 strncpy(delayed_undo_name, name, 63);
1193 mainqenter(UNDOPUSH, 1);
1196 void screenmain(void)
1200 int onload_script = 0;
1202 window_make_active(mainwin);
1205 unsigned short event;
1209 flush_extqd_events();
1210 if (nafterqitems && !qtest()) {
1211 append_afterqueue();
1212 event= val= ascii= 0;
1214 event= screen_qread(&val, &ascii);
1217 // window_make_active(mainwin); // (only for inputchange, removed, (ton))
1219 if (event==INPUTCHANGE) {
1220 window_make_active(mainwin);
1224 /* If the main window is active, find the current active ScrArea
1225 * underneath the mouse cursor, updating the headers & cursor for
1226 * the appropriate internal window if things have changed.
1228 * If the main window is not active, deactivate the internal
1231 if (has_input || g_activearea==NULL || G.curscreen->winakt) {
1232 ScrArea *newactarea;
1236 getmouseco_sc(mval);
1237 newactarea= screen_find_area_for_pt(G.curscreen, mval);
1240 if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
1241 newactwin= newactarea->headwin;
1243 newactwin= newactarea->win;
1249 if (newactarea && (newactarea != g_activearea)) {
1250 if (g_activearea) scrarea_queue_headredraw(g_activearea);
1251 scrarea_queue_headredraw(newactarea);
1252 set_cursor(newactarea->cursor);
1253 g_activearea= newactarea;
1255 /* when you move mouse from header to window, buttons can remain hilited otherwise */
1256 if(newactwin != G.curscreen->winakt) {
1257 if (g_activearea) scrarea_queue_headredraw(g_activearea);
1259 G.curscreen->winakt= newactwin;
1261 if (G.curscreen->winakt) {
1262 areawinset(G.curscreen->winakt);
1263 set_cursor(choose_cursor(g_activearea));
1268 scrarea_queue_headredraw(g_activearea);
1271 G.curscreen->winakt= 0;
1275 if (event==WINCLOSE) {
1278 else if (event==DRAWEDGES) {
1281 else if (event==RESHAPE) {
1286 else if (event==REDRAW) {
1290 else if( event==UNDOPUSH) {
1291 BIF_undo_push(delayed_undo_name);
1293 else if (event==AUTOSAVE_FILE) {
1294 BIF_write_autosave();
1296 else if (event==LOAD_FILE) {
1297 BIF_read_file(ext_load_str);
1298 sound_initialize_sounds();
1300 else if ((event==ONLOAD_SCRIPT) && BPY_has_onload_script()) {
1301 /* event queued in setup_app_data() in blender.c, where G.f is checked */
1303 firsttime = 1; /* see last 'if' in this function */
1309 if (!g_activearea) {
1312 else if (event==QKEY) {
1313 if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT||g_activearea->spacetype==SPACE_SCRIPT);
1316 if(okee("Quit Blender")) exit_usiblender();
1321 else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
1322 if(textediting==0 && val && (G.qual & LR_CTRLKEY)) {
1323 bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
1324 if(is_allowed_to_change_screen(sc)) setscreen(sc);
1329 else if (!G.curscreen->winakt) {
1333 getmouseco_sc(mval);
1334 actedge= screen_find_active_scredge(G.curscreen, mval);
1337 if (scredge_is_horizontal(actedge)) {
1338 set_cursor(CURSOR_Y_MOVE);
1340 set_cursor(CURSOR_X_MOVE);
1342 // this does global hotkeys too
1343 screen_edge_edit_event(g_activearea, actedge, event, val);
1345 set_cursor(CURSOR_STD);
1350 else if (event==ZKEY) {
1351 if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
1352 extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
1354 int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
1357 case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
1358 case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
1359 case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
1360 case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
1361 case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
1364 g_activearea->head_swap= 0;
1365 g_activearea->win_swap= 0;
1372 else if (event==SPACEKEY) {
1373 if((g_activearea->spacetype!=SPACE_TEXT) && val && (G.qual & LR_SHIFTKEY)) {
1379 if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT||g_activearea->spacetype==SPACE_SCRIPT);
1380 else if(G.qual==0) {
1381 if(val) toolbox_n();
1386 else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
1387 if(val && (G.qual & LR_CTRLKEY)) {
1394 if (towin && event) {
1395 if (blenderqread(event, val)) // the global keys
1396 addqueue_ext(G.curscreen->winakt, event, val, ascii);
1399 /* only process subwindow queue's once the
1400 * main queue has been emptyied.
1403 if (event==0 || event==EXECUTE) {
1404 screen_dispatch_events();
1408 GLenum error = glGetError();
1410 printf("GL error: %s\n", gluErrorString(error));
1412 /* Bizar hack. The event queue has mutated... */
1413 if ( (firsttime) && (event == 0) ) {
1415 if (onload_script) {
1416 /* OnLoad scriptlink */
1417 BPY_do_pyscript(&G.scene->id, SCRIPT_ONLOAD);
1420 else if (G.fileflags & G_FILE_AUTOPLAY) {
1421 // SET AUTOPLAY in G.flags for
1424 G.flags |= G_FILE_AUTOPLAY;
1425 area_autoplayscreen();
1427 // Let The Games Begin
1428 // fake a 'p' keypress
1430 mainqenter(PKEY, 1);
1432 extern char datatoc_splash_jpg[];
1433 extern int datatoc_splash_jpg_size;
1435 //if (! ((G.main->versionfile >= G.version)
1436 // || G.save_over)) {
1437 splash((void *)datatoc_splash_jpg,
1438 datatoc_splash_jpg_size, NULL);
1447 //#ifdef _WIN32 // FULLSCREEN
1448 void mainwindow_toggle_fullscreen(int fullscreen){
1449 if (fullscreen) U.uiflag |= USER_FLIPFULLSCREEN;
1450 else U.uiflag &= ~USER_FLIPFULLSCREEN;
1452 window_toggle_fullscreen(mainwin, fullscreen);
1456 void mainwindow_raise(void) {
1457 window_raise(mainwin);
1460 void mainwindow_make_active(void) {
1461 window_make_active(mainwin);
1464 void mainwindow_close(void) {
1465 window_destroy(mainwin);
1469 void mainwindow_set_filename_to_title(char *filename) {
1470 char str[FILE_MAXDIR + FILE_MAXFILE];
1471 char dir[FILE_MAXDIR];
1472 char file[FILE_MAXFILE];
1474 BLI_split_dirfile(filename, dir, file);
1476 if(BLI_streq(file, ".B.blend") || filename[0] =='\0')
1477 sprintf(str, "Blender");
1479 sprintf(str, "Blender [%s]", filename);
1481 window_set_title(mainwin, str);
1484 /* ********* AREAS ************* */
1486 void setprefsize(int stax, int stay, int sizx, int sizy)
1488 int scrwidth, scrheight;
1490 winlay_get_screensize(&scrwidth, &scrheight);
1492 if(sizx<320) sizx= 320;
1493 if(sizy<256) sizy= 256;
1495 if(stay+sizy>scrheight) {
1496 fprintf(stderr," height prob \n");
1497 sizy= scrheight-stay;
1500 if(sizx<320 || sizy<256) {
1501 printf("ERROR: illegal prefsize\n");
1514 static ScrVert *screen_addvert(bScreen *sc, short x, short y)
1516 ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
1520 BLI_addtail(&sc->vertbase, sv);
1524 static void sortscrvert(ScrVert **v1, ScrVert **v2)
1535 static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1537 ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
1539 sortscrvert(&v1, &v2);
1543 BLI_addtail(&sc->edgebase, se);
1547 static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1551 sortscrvert(&v1, &v2);
1552 for (se= sc->edgebase.first; se; se= se->next)
1553 if(se->v1==v1 && se->v2==v2)
1559 static void removedouble_scrverts(void)
1565 verg= G.curscreen->vertbase.first;
1567 if(verg->newv==0) { /* !!! */
1570 if(v1->newv==0) { /* !?! */
1571 if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
1572 /* printf("doublevert\n"); */
1582 /* replace pointers in edges and faces */
1583 se= G.curscreen->edgebase.first;
1585 if(se->v1->newv) se->v1= se->v1->newv;
1586 if(se->v2->newv) se->v2= se->v2->newv;
1587 /* edges changed: so.... */
1588 sortscrvert(&(se->v1), &(se->v2));
1591 sa= G.curscreen->areabase.first;
1593 if(sa->v1->newv) sa->v1= sa->v1->newv;
1594 if(sa->v2->newv) sa->v2= sa->v2->newv;
1595 if(sa->v3->newv) sa->v3= sa->v3->newv;
1596 if(sa->v4->newv) sa->v4= sa->v4->newv;
1601 verg= G.curscreen->vertbase.first;
1605 BLI_remlink(&G.curscreen->vertbase, verg);
1613 static void removenotused_scrverts(void)
1618 /* we assume edges are ok */
1620 se= G.curscreen->edgebase.first;
1627 sv= G.curscreen->vertbase.first;
1631 BLI_remlink(&G.curscreen->vertbase, sv);
1639 static void removedouble_scredges(void)
1641 ScrEdge *verg, *se, *sn;
1644 verg= G.curscreen->edgebase.first;
1649 if(verg->v1==se->v1 && verg->v2==se->v2) {
1650 BLI_remlink(&G.curscreen->edgebase, se);
1659 static void removenotused_scredges(void)
1665 /* sets flags when edge is used in area */
1666 sa= G.curscreen->areabase.first;
1668 se= screen_findedge(G.curscreen, sa->v1, sa->v2);
1669 if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
1671 se= screen_findedge(G.curscreen, sa->v2, sa->v3);
1672 if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
1674 se= screen_findedge(G.curscreen, sa->v3, sa->v4);
1675 if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
1677 se= screen_findedge(G.curscreen, sa->v4, sa->v1);
1678 if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
1683 se= G.curscreen->edgebase.first;
1687 BLI_remlink(&G.curscreen->edgebase, se);
1695 void calc_arearcts(ScrArea *sa)
1698 if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+1;
1699 else sa->totrct.xmin= sa->v1->vec.x;
1700 if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-1;
1701 else sa->totrct.xmax= sa->v4->vec.x;
1703 if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+1;
1704 else sa->totrct.ymin= sa->v1->vec.y;
1705 if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-1;
1706 else sa->totrct.ymax= sa->v2->vec.y;
1708 sa->winrct= sa->totrct;
1709 sa->headrct= sa->totrct;
1710 if(sa->headertype) {
1711 if(sa->headertype==HEADERDOWN) {
1712 sa->headrct.ymax= sa->headrct.ymin+HEADERY;
1713 sa->winrct.ymin= sa->headrct.ymax+1;
1715 else if(sa->headertype==HEADERTOP) {
1716 sa->headrct.ymin= sa->headrct.ymax-HEADERY;
1717 sa->winrct.ymax= sa->headrct.ymin-1;
1721 sa->headrct.ymax= sa->headrct.ymin;
1723 if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
1726 sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
1727 sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
1730 static void openheadwin(ScrArea *sa)
1732 sa->headwin= myswinopen(G.curscreen->mainwin,
1733 sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1735 glMatrixMode(GL_MODELVIEW);
1737 areawinar[sa->headwin]= sa; /* oterwise addqueue does not work */
1738 addqueue(sa->headwin, CHANGED, 1);
1741 static void openareawin(ScrArea *sa)
1743 sa->win= myswinopen(G.curscreen->mainwin,
1744 sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1746 areawinar[sa->win]= sa; /* otherwise addqueue does not work */
1747 addqueue(sa->win, CHANGED, 1);
1750 static void closeheadwin(ScrArea *sa)
1752 if(sa->headwin) mywinclose(sa->headwin);
1756 static void closeareawin(ScrArea *sa)
1758 uiFreeBlocksWin(&sa->uiblocks, sa->win);
1760 if(sa->win) mywinclose(sa->win);
1764 static void del_area(ScrArea *sa)
1769 freespacelist(&sa->spacedata);
1771 uiFreeBlocks(&sa->uiblocks);
1772 uiFreePanels(&sa->panels);
1774 if(sa==curarea) curarea= 0;
1775 if(sa==g_activearea) g_activearea= 0;
1779 static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
1781 Panel *pa1, *pa2, *patab;
1782 ScriptLink *slink1 = &sa1->scriptlink, *slink2 = &sa2->scriptlink;
1784 sa1->headertype= sa2->headertype;
1785 sa1->spacetype= sa2->spacetype;
1786 Mat4CpyMat4(sa1->winmat, sa2->winmat);
1788 freespacelist(&sa1->spacedata);
1789 duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
1791 BLI_freelistN(&sa1->panels);
1792 duplicatelist(&sa1->panels, &sa2->panels);
1794 /* space handler script links */
1795 if (slink1->totscript) {
1796 MEM_freeN(slink1->scripts);
1797 MEM_freeN(slink1->flag);
1798 slink1->totscript = 0;
1800 if (slink2->totscript) {
1801 slink1->scripts = MEM_dupallocN(slink2->scripts);
1802 slink1->flag = MEM_dupallocN(slink2->flag);
1803 slink1->totscript = slink2->totscript;
1807 pa1= sa1->panels.first;
1810 patab= sa1->panels.first;
1811 pa2= sa2->panels.first;
1813 if( pa1->paneltab == pa2) {
1814 pa1->paneltab = patab;
1824 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
1826 ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
1827 sa->cursor= CURSOR_STD;
1832 sa->headertype= headertype;
1833 sa->spacetype= spacetype;
1837 if (sa->headertype) openheadwin(sa);
1840 BLI_addtail(&sc->areabase, sa);
1844 static int rcti_eq(rcti *a, rcti *b) {
1845 return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
1846 (a->ymin==b->ymin && a->ymax==b->ymax));
1849 static void testareas(void)
1853 /* test for header, if removed, or moved */
1854 /* test for window, if removed, or moved */
1856 sa= G.curscreen->areabase.first;
1858 rcti oldhr= sa->headrct;
1859 rcti oldwr= sa->winrct;
1865 /* ilegally scaled down area.... */
1866 if(sa->totrct.xmin>=sa->totrct.xmax || sa->totrct.ymin>=sa->totrct.ymax) {
1868 BLI_remlink(&G.curscreen->areabase, sa);
1870 printf("Warning, removed zero sized window from screen %s\n", G.curscreen->id.name+2);
1875 if (!rcti_eq(&oldhr, &sa->headrct)) {
1876 mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1877 addqueue(sa->headwin, CHANGED, 1);
1880 if(sa->headbutlen<sa->winx) {
1882 addqueue(sa->headwin, CHANGED, 1);
1884 else if(sa->headbutofs+sa->winx > sa->headbutlen) {
1885 sa->headbutofs= sa->headbutlen-sa->winx;
1886 addqueue(sa->headwin, CHANGED, 1);
1890 if (!rcti_eq(&oldwr, &sa->winrct)) {
1891 mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1892 addqueue(sa->win, CHANGED, 1);
1898 /* remake global windowarray */
1899 memset(areawinar, 0, sizeof(void *)*MAXWIN);
1900 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1901 areawinar[sa->headwin]= sa;
1902 areawinar[sa->win]= sa;
1905 /* test if winakt is OK */
1906 if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
1909 static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
1911 /* test if edge is in area, if not,
1912 then find an area that has it */
1914 ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
1917 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1918 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1919 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1920 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1922 if(se1!=se && se2!=se && se3!=se && se4!=se) {
1924 sa= G.curscreen->areabase.first;
1926 /* a bit optimise? */
1927 if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
1928 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1929 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1930 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1931 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1932 if(se1==se || se2==se || se3==se || se4==se) return sa;
1938 return sa; /* is null when not find */
1941 ScrArea *closest_bigger_area(void)
1943 ScrArea *sa, *big=0;
1944 float cent[3], vec[3],len, len1, len2, len3, dist=1000;
1947 getmouseco_sc(mval);
1953 sa= G.curscreen->areabase.first;
1956 if(sa->winy>=curarea->winy) {
1958 /* mimimum of the 4 corners */
1959 vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
1960 len= VecLenf(vec, cent);
1961 vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
1962 len1= VecLenf(vec, cent);
1963 vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
1964 len2= VecLenf(vec, cent);
1965 vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
1966 len3= VecLenf(vec, cent);
1968 len= MIN4(len, len1, len2, len3);
1971 vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
1972 vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
1974 len+= 0.5*VecLenf(vec, cent);
1977 len-= sa->winy+sa->winx;
1989 else return curarea;
1992 /* ************ SCREEN MANAGEMENT ************** */
1994 static int statechanged= 0;
1995 void BIF_wait_for_statechange(void)
1997 if (!statechanged) {
1998 /* Safety, don't wait more than 0.1 seconds */
1999 double stime= PIL_check_seconds_timer();
2000 while (!statechanged) {
2001 winlay_process_events(1);
2002 if ((PIL_check_seconds_timer()-stime)>0.1) break;
2006 else PIL_sleep_ms(3); /* statechanged can be set '1' while holding mousebutton, causing locks */
2009 void getmouse(short *mval)
2011 winlay_process_events(0);
2012 window_get_mouse(mainwin, mval);
2014 short get_qual(void)
2016 winlay_process_events(0);
2017 return window_get_qual(mainwin);
2019 short get_mbut(void)
2021 winlay_process_events(0);
2022 return window_get_mbut(mainwin);
2025 void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
2030 /* accept the extended ascii set (ton) */
2031 if( !val || ascii<32 ) {
2035 mainqenter_ext(evt, val, ascii);
2038 /* ScrVert ordering in a ScrArea:
2047 static bScreen *addscreen(char *name) /* use setprefsize() if you want something else than a full windpw */
2049 /* this function sets variabele G.curscreen,
2050 * that global is about used everywhere!
2053 ScrVert *sv1, *sv2, *sv3, *sv4;
2054 short startx, starty, endx, endy;
2056 sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
2062 winlay_get_screensize(&prefsizx, &prefsizy);
2067 endx= prefstax+prefsizx-1;
2068 endy= prefstay+prefsizy-1;
2070 sc->startx= startx; sc->starty= starty;
2071 sc->endx= endx; sc->endy= endy;
2072 sc->sizex= sc->endx-sc->startx+1;
2073 sc->sizey= sc->endy-sc->starty+1;
2079 //#ifdef _WIN32 // FULLSCREEN
2080 if (G.windowstate == G_WINDOWSTATE_FULLSCREEN)
2081 mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, G_WINDOWSTATE_FULLSCREEN);
2083 mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
2085 mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
2089 printf("ERROR: Unable to open Blender window\n");
2093 window_set_handler(mainwin, add_to_mainqueue, NULL);
2097 /* for visual speed, but still needed? */
2098 glClearColor(.55, .55, .55, 0.0);
2099 glClear(GL_COLOR_BUFFER_BIT);
2100 window_swap_buffers(mainwin);
2102 warp_pointer(sc->sizex/2, sc->sizey/2);
2104 mainqenter(REDRAW, 1);
2109 sv1= screen_addvert(sc, 0, 0);
2110 sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
2111 sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
2112 sv4= screen_addvert(sc, sc->sizex-1, 0);
2114 screen_addedge(sc, sv1, sv2);
2115 screen_addedge(sc, sv2, sv3);
2116 screen_addedge(sc, sv3, sv4);
2117 screen_addedge(sc, sv4, sv1);
2119 screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
2126 void setscreen(bScreen *sc)
2132 if(sc->full) { /* find associated full */
2133 sc1= G.main->screen.first;
2135 sa= sc1->areabase.first;
2142 if(sc1==0) printf("setscreen error\n");
2145 /* de-activate G.curscreen */
2146 if (G.curscreen && G.curscreen != sc) {
2147 sa= G.curscreen->areabase.first;
2149 if(sa->win) mywinclose(sa->win);
2151 if(sa->headwin) mywinclose(sa->headwin);
2154 uiFreeBlocks(&sa->uiblocks);
2159 else if(G.curscreen) markdirty_all(); /* at least redraw */
2161 if (G.curscreen != sc) {
2162 mywinset(sc->mainwin);
2167 for (sa= sc->areabase.first; sa; sa= sa->next) {
2169 /* if (sa->win || sa->headwin) */
2170 /* printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
2173 if (!sa->headwin && sa->headertype)
2177 /* recalculate winakt */
2178 getmouseco_sc(mval);
2180 test_scale_screen(sc);
2183 for(sa= sc->areabase.first; sa; sa= sa->next) {
2186 for(sl= sa->spacedata.first; sl; sl= sl->next) {
2189 if(sl->spacetype==SPACE_OOPS) {
2190 SpaceOops *soops= (SpaceOops *) sl;
2192 /* patch for old files */
2193 if(soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
2194 init_v2d_oops(sa, soops);
2197 else if(sl->spacetype==SPACE_BUTS) {
2198 SpaceButs *sbuts= (SpaceButs *)sl;
2199 sbuts->re_align= 1; // force an align call, maybe new panels were added, also for after file reading
2203 sa->cursor= CURSOR_STD;
2209 G.curscreen->winakt= 0;
2210 curarea= sc->areabase.first;
2212 mainqenter(DRAWEDGES, 1);
2213 dodrawscreen= 1; /* patch! even gets lost,,,? */
2215 winqueue_break= 1; /* means leave queue everywhere */
2218 static void splitarea(ScrArea *sa, char dir, float fac);
2220 void area_fullscreen(void) /* with curarea */
2222 /* this function toggles: if area is full then the parent will be restored */
2223 bScreen *sc, *oldscreen;
2224 ScrArea *newa, *old;
2225 short headertype, fulltype;
2228 sc= curarea->full; /* the old screen */
2229 fulltype = sc->full;
2231 // refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
2234 if (fulltype != SCREENAUTOPLAY || (G.flags & G_FILE_AUTOPLAY) == 0) {
2238 old= sc->areabase.first;
2240 if(old->full) break;
2243 if(old==0) {error("something wrong in areafullscreen"); return;}
2245 if (fulltype == SCREENAUTOPLAY) {
2246 // in autoplay screens the headers are disabled by
2247 // default. So use the old headertype instead
2248 headertype = old->headertype;
2250 // normal fullscreen. Use current headertype
2251 headertype = curarea->headertype;
2254 copy_areadata(old, curarea);
2255 old->headertype = headertype;
2259 unlink_screen(G.curscreen);
2260 free_libblock(&G.main->screen, G.curscreen);
2268 /* is there only 1 area? */
2269 if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
2270 if(curarea->spacetype==SPACE_INFO) return;
2272 G.curscreen->full = SCREENFULL;
2275 oldscreen= G.curscreen;
2276 sc= addscreen("temp"); /* this sets G.curscreen */
2278 splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
2279 newa= sc->areabase.first;
2280 newspace(newa->next, SPACE_INFO);
2283 G.curscreen= oldscreen; /* needed because of setscreen */
2286 copy_areadata(newa, curarea);
2288 curarea->full= oldscreen;
2289 newa->full= oldscreen;
2290 newa->next->full= oldscreen;
2297 static void area_autoplayscreen(void)
2299 bScreen *sc, *oldscreen;
2300 ScrArea *newa, *old, *sa;
2302 if (curarea->full) {
2306 if (curarea->full == NULL) {
2307 sa = G.curscreen->areabase.first;
2309 if (sa->spacetype == SPACE_VIEW3D) {
2316 areawinset(sa->win);
2317 G.curscreen->full = SCREENAUTOPLAY;
2320 oldscreen= G.curscreen;
2321 sc= addscreen("temp"); /* this sets G.curscreen */
2323 newa= sc->areabase.first;
2326 G.curscreen= oldscreen; /* because of setscreen */
2328 /* copy area settings */
2329 copy_areadata(newa, curarea);
2330 newa->headertype= 0;
2332 curarea->full= oldscreen;
2333 newa->full= oldscreen;
2341 static void copy_screen(bScreen *to, bScreen *from)
2349 winqueue_break= 1; /* leave queues everywhere */
2351 duplicatelist(&to->vertbase, &from->vertbase);
2352 duplicatelist(&to->edgebase, &from->edgebase);
2353 duplicatelist(&to->areabase, &from->areabase);
2355 s1= from->vertbase.first;
2356 s2= to->vertbase.first;
2362 se= to->edgebase.first;
2364 se->v1= se->v1->newv;
2365 se->v2= se->v2->newv;
2366 sortscrvert(&(se->v1), &(se->v2));
2370 sa= to->areabase.first;
2371 saf= from->areabase.first;
2373 sa->v1= sa->v1->newv;
2374 sa->v2= sa->v2->newv;
2375 sa->v3= sa->v3->newv;
2376 sa->v4= sa->v4->newv;
2380 sa->spacedata.first= sa->spacedata.last= NULL;
2381 sa->uiblocks.first= sa->uiblocks.last= NULL;
2382 sa->panels.first= sa->panels.last= NULL;
2383 copy_areadata(sa, saf);
2389 /* put at zero (needed?) */
2390 s1= from->vertbase.first;
2397 void duplicate_screen(void)
2399 bScreen *sc, *oldscreen;
2401 if(G.curscreen->full != SCREENNORMAL) return;
2403 /* make new screen: */
2405 oldscreen= G.curscreen;
2406 sc= addscreen(oldscreen->id.name+2); /* this sets G.curscreen */
2407 copy_screen(sc, oldscreen);
2409 G.curscreen= oldscreen;
2415 /* ************ END SCREEN MANAGEMENT ************** */
2416 /* ************ JOIN/SPLIT/MOVE ************** */
2418 typedef struct point{
2422 /* draw vertical shape visualising future joining (left as well
2423 * right direction of future joining) */
2424 static void draw_horizontal_join_shape(ScrArea *sa, char dir)
2429 float width = sa->v3->vec.x - sa->v1->vec.x;
2430 float height = sa->v3->vec.y - sa->v1->vec.y;
2441 points[0].x = sa->v1->vec.x;
2442 points[0].y = sa->v1->vec.y + height/2;
2444 points[1].x = sa->v1->vec.x;
2445 points[1].y = sa->v1->vec.y;
2447 points[2].x = sa->v4->vec.x - w;
2448 points[2].y = sa->v4->vec.y;
2450 points[3].x = sa->v4->vec.x - w;
2451 points[3].y = sa->v4->vec.y + height/2 - 2*h;
2453 points[4].x = sa->v4->vec.x - 2*w;
2454 points[4].y = sa->v4->vec.y + height/2;
2456 points[5].x = sa->v4->vec.x - w;
2457 points[5].y = sa->v4->vec.y + height/2 + 2*h;
2459 points[6].x = sa->v3->vec.x - w;
2460 points[6].y = sa->v3->vec.y;
2462 points[7].x = sa->v2->vec.x;
2463 points[7].y = sa->v2->vec.y;
2465 points[8].x = sa->v4->vec.x;
2466 points[8].y = sa->v4->vec.y + height/2 - h;
2468 points[9].x = sa->v4->vec.x;
2469 points[9].y = sa->v4->vec.y + height/2 + h;
2472 /* when direction is left, then we flip direction of arrow */
2473 float cx = sa->v1->vec.x + width;
2476 points[i].x = -points[i].x;
2477 points[i].x += sa->v1->vec.x;
2481 glBegin(GL_POLYGON);
2483 glVertex2f(points[i].x, points[i].y);
2485 glBegin(GL_POLYGON);
2487 glVertex2f(points[i].x, points[i].y);
2488 glVertex2f(points[0].x, points[0].y);
2491 glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
2492 glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
2495 /* draw vertical shape visualising future joining (up/down direction) */
2496 static void draw_vertical_join_shape(ScrArea *sa, char dir)
2501 float width = sa->v3->vec.x - sa->v1->vec.x;
2502 float height = sa->v3->vec.y - sa->v1->vec.y;
2513 points[0].x = sa->v1->vec.x + width/2;
2514 points[0].y = sa->v3->vec.y;
2516 points[1].x = sa->v2->vec.x;
2517 points[1].y = sa->v2->vec.y;
2519 points[2].x = sa->v1->vec.x;
2520 points[2].y = sa->v1->vec.y + h;
2522 points[3].x = sa->v1->vec.x + width/2 - 2*w;
2523 points[3].y = sa->v1->vec.y + h;
2525 points[4].x = sa->v1->vec.x + width/2;
2526 points[4].y = sa->v1->vec.y + 2*h;
2528 points[5].x = sa->v1->vec.x + width/2 + 2*w;
2529 points[5].y = sa->v1->vec.y + h;
2531 points[6].x = sa->v4->vec.x;
2532 points[6].y = sa->v4->vec.y + h;
2534 points[7].x = sa->v3->vec.x;
2535 points[7].y = sa->v3->vec.y;
2537 points[8].x = sa->v1->vec.x + width/2 - w;
2538 points[8].y = sa->v1->vec.y;
2540 points[9].x = sa->v1->vec.x + width/2 + w;
2541 points[9].y = sa->v1->vec.y;
2544 /* when direction is up, then we flip direction of arrow */
2545 float cy = sa->v1->vec.y + height;
2548 points[i].y = -points[i].y;
2549 points[i].y += sa->v1->vec.y;
2553 glBegin(GL_POLYGON);
2555 glVertex2f(points[i].x, points[i].y);
2557 glBegin(GL_POLYGON);
2559 glVertex2f(points[i].x, points[i].y);
2560 glVertex2f(points[0].x, points[0].y);
2563 glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
2564 glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
2567 /* draw join shape due to direction of joining */
2568 static void draw_join_shape(ScrArea *sa, char dir)
2570 if(dir=='u' || dir=='d')
2571 draw_vertical_join_shape(sa, dir);
2573 draw_horizontal_join_shape(sa, dir);
2576 /* draw screen area darker with arrow (visualisation of future joining) */
2577 static void scrarea_draw_shape_dark(ScrArea *sa, char dir)
2579 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2581 glColor4ub(0, 0, 0, 105);
2582 draw_join_shape(sa, dir);
2583 glDisable(GL_BLEND);
2586 /* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */
2587 static void scrarea_draw_shape_light(ScrArea *sa, char dir)
2589 glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
2591 /* value 181 was hardly computed: 181~105 */
2592 glColor4ub(255, 255, 255, 181);
2593 draw_join_shape(sa, dir);
2594 glDisable(GL_BLEND);
2597 static void joinarea_interactive(ScrArea *area, ScrEdge *onedge)
2599 struct ScrArea *sa1 = area, *sa2, *scr;
2600 struct ScrArea *up=0, *down=0, *right=0, *left=0;
2602 unsigned short event;
2603 short ok=0, val=0, mval[2];
2606 sa1 = test_edge_area(sa1, onedge);
2609 /* find directions with same edge */
2610 sa2= G.curscreen->areabase.first;
2613 se= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
2614 if(onedge==se) right= sa2;
2615 se= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
2616 if(onedge==se) down= sa2;
2617 se= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
2618 if(onedge==se) left= sa2;
2619 se= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
2620 if(onedge==se) up= sa2;
2654 mywinset(G.curscreen->mainwin);
2656 /* initial set up screen area asigned for destroying */
2659 /* set up standard cursor */
2660 set_cursor(CURSOR_STD);
2662 /* should already have a good matrix */
2663 glReadBuffer(GL_FRONT);
2664 glDrawBuffer(GL_FRONT);
2666 /* to prevent flickering after clicking at "Join Areas " */
2667 getmouseco_sc(mval);
2669 if(scr==left && mval[0]>=onedge->v1->vec.x) scr = right;
2670 else if(scr==right && mval[0]<onedge->v1->vec.x) scr = left;
2673 if(scr==down && mval[1]>=onedge->v1->vec.y) scr = up;
2674 else if(scr==up && mval[1]<onedge->v1->vec.y) scr = down;
2677 /* draw scr screen area with dark shape */
2679 scrarea_draw_shape_dark(scr,'r');
2681 scrarea_draw_shape_dark(scr,'l');
2683 scrarea_draw_shape_dark(scr,'d');
2685 scrarea_draw_shape_dark(scr,'u');
2688 /* "never ending loop" of interactive selection */
2690 getmouseco_sc(mval);
2692 /* test if position of mouse is on the "different side" of
2695 if(scr==left && mval[0]>=onedge->v1->vec.x) {
2696 scrarea_draw_shape_light(scr,'r');
2698 scrarea_draw_shape_dark(scr,'l');
2700 else if(scr==right && mval[0]<onedge->v1->vec.x) {
2701 scrarea_draw_shape_light(scr,'l');
2703 scrarea_draw_shape_dark(scr,'r');
2707 if(scr==down && mval[1]>=onedge->v1->vec.y) {
2708 scrarea_draw_shape_light(scr,'u');
2710 scrarea_draw_shape_dark(scr,'d');
2712 else if(scr==up && mval[1]<onedge->v1->vec.y){
2713 scrarea_draw_shape_light(scr,'d');
2715 scrarea_draw_shape_dark(scr,'u');
2720 /* get pressed keys and mouse buttons */
2721 event = extern_qread(&val);
2723 /* confirm joining of two screen areas */
2724 if(val && event==LEFTMOUSE) ok= 1;
2726 /* cancel joining of joining */
2727 if(val && (event==ESCKEY || event==RIGHTMOUSE)) ok= -1;
2732 glReadBuffer(GL_BACK);
2733 glDrawBuffer(GL_BACK);
2735 /* joining af screen areas was confirmed ... proceed joining */
2745 screen_addedge(G.curscreen, sa1->v2, sa1->v3);
2746 screen_addedge(G.curscreen, sa1->v1, sa1->v4);
2751 screen_addedge(G.curscreen, sa1->v1, sa1->v2);
2752 screen_addedge(G.curscreen, sa1->v3, sa1->v4);
2754 else if(sa2==right) {
2757 screen_addedge(G.curscreen, sa1->v2, sa1->v3);
2758 screen_addedge(G.curscreen, sa1->v1, sa1->v4);
2760 else if(sa2==down) {
2763 screen_addedge(G.curscreen, sa1->v1, sa1->v2);
2764 screen_addedge(G.curscreen, sa1->v3, sa1->v4);
2768 BLI_remlink(&G.curscreen->areabase, sa2);
2771 removedouble_scredges();
2772 removenotused_scredges();
2773 removenotused_scrverts();
2776 mainqenter(DRAWEDGES, 1);
2778 /* test cursor en inputwindow */
2779 mainqenter(MOUSEY, -1);
2783 static short testsplitpoint(ScrArea *sa, char dir, float fac)
2784 /* return 0: no split possible */
2785 /* else return (integer) screencoordinate split point */
2789 /* area big enough? */
2790 if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
2791 if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
2794 if(fac<0.0) fac= 0.0;
2795 if(fac>1.0) fac= 1.0;
2798 y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
2800 if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY)
2801 y= sa->v2->vec.y- HEADERY;
2803 else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY)
2804 y= sa->v1->vec.y+ HEADERY;
2806 else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
2807 else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
2808 else y-= (y % AREAGRID);
2813 x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
2814 if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
2815 else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
2816 else x-= (x % AREAGRID);
2822 static void splitarea(ScrArea *sa, char dir, float fac)
2831 split= testsplitpoint(sa, dir, fac);
2832 if(split==0) return;
2836 areawinset(sa->win);
2840 sv1= screen_addvert(sc, sa->v1->vec.x, split);
2841 sv2= screen_addvert(sc, sa->v4->vec.x, split);
2844 screen_addedge(sc, sa->v1, sv1);
2845 screen_addedge(sc, sv1, sa->v2);
2846 screen_addedge(sc, sa->v3, sv2);
2847 screen_addedge(sc, sv2, sa->v4);
2848 screen_addedge(sc, sv1, sv2);
2850 /* new areas: top */
2851 newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
2852 copy_areadata(newa, sa);
2861 sv1= screen_addvert(sc, split, sa->v1->vec.y);
2862 sv2= screen_addvert(sc, split, sa->v2->vec.y);
2865 screen_addedge(sc, sa->v1, sv1);
2866 screen_addedge(sc, sv1, sa->v4);
2867 screen_addedge(sc, sa->v2, sv2);
2868 screen_addedge(sc, sv2, sa->v3);
2869 screen_addedge(sc, sv1, sv2);
2871 /* new areas: left */
2872 newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
2873 copy_areadata(newa, sa);
2880 if(sa->spacetype==SPACE_BUTS) {
2881 addqueue(sa->win, UI_BUT_EVENT, B_BUTSHOME);
2882 addqueue(newa->win, UI_BUT_EVENT, B_BUTSHOME);
2885 /* remove double vertices en edges */
2886 removedouble_scrverts();
2887 removedouble_scredges();
2888 removenotused_scredges();
2890 mainqenter(DRAWEDGES, 1);
2891 dodrawscreen= 1; /* patch! event gets lost,,,? */
2895 static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
2897 int split= testsplitpoint(sa, dir, fac);
2901 sdrawXORline(sa->totrct.xmin, split, sa->totrct.xmax, split);
2902 sdrawXORline(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
2904 sdrawXORline(split, sa->totrct.ymin, split, sa->totrct.ymax);
2905 sdrawXORline(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
2910 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
2912 ScrArea *scr, *sa= area;
2914 unsigned short event;
2915 short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
2918 if(sa->win==0) return;
2919 if(sa->full) return;
2921 dir= scredge_is_horizontal(onedge)?'v':'h';
2923 mywinset(G.curscreen->mainwin);
2924 /* should already have a good matrix */
2925 glReadBuffer(GL_FRONT);
2926 glDrawBuffer(GL_FRONT);
2928 /* keep track of grid and minsize */
2930 getmouseco_sc(mval);
2932 /* this part of code allows to choose, what window will be splited */
2933 /* cursor is out of the current ScreenArea */
2934 if((mval[0] < sa->v1->vec.x) || (mval[0] > sa->v3->vec.x) ||
2935 (mval[1] < sa->v1->vec.y) || (mval[1] > sa->v3->vec.y)){
2936 scr= (ScrArea*)G.curscreen->areabase.first;
2938 if((mval[0] > scr->v1->vec.x) && (mval[0] < scr->v4->vec.x) &&
2939 (mval[1] < scr->v2->vec.y) && (mval[1] > scr->v1->vec.y)){
2940 /* test: is ScreenArea enough big for splitting */
2941 short tsplit= testsplitpoint(scr, dir, fac);
2944 /* delete old line from previous ScreenArea */
2945 if(!first) scrarea_draw_splitpoint(sa, dir, fac);
2955 if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2957 scrarea_draw_splitpoint(sa, dir, fac);
2961 fac= mval[1]- (sa->v1->vec.y);
2962 fac/= sa->v2->vec.y- sa->v1->vec.y;
2964 fac= mval[0]- sa->v1->vec.x;
2965 fac/= sa->v4->vec.x- sa->v1->vec.x;
2968 split= testsplitpoint(sa, dir, fac);
2970 scrarea_draw_splitpoint(sa, dir, fac);
2980 event= extern_qread(&val);
2982 /* change direction of splitting between horizontal and vertical
2983 * patch was offered by Guillaume */
2984 if(val && (event==TABKEY || event==MIDDLEMOUSE)) {
2985 scrarea_draw_splitpoint(sa, dir, fac);
2988 set_cursor(CURSOR_Y_MOVE);
2991 set_cursor(CURSOR_X_MOVE);
2996 if(val && event==LEFTMOUSE) {
2998 fac= split- (sa->v1->vec.y);
2999 fac/= sa->v2->vec.y- sa->v1->vec.y;
3002 fac= split- sa->v1->vec.x;
3003 fac/= sa->v4->vec.x- sa->v1->vec.x;
3007 if(val && (event==ESCKEY || event==RIGHTMOUSE)) {
3014 scrarea_draw_splitpoint(sa, dir, fac);
3017 glReadBuffer(GL_BACK);
3018 glDrawBuffer(GL_BACK);
3021 splitarea(sa, dir, fac);
3022 mainqenter(DRAWEDGES, 1);
3023 dodrawscreen= 1; /* patch! event gets lost,,,? */
3027 View3D *find_biggest_view3d(void)
3029 ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
3032 return (View3D*) sa->spacedata.first;
3038 ScrArea *find_biggest_area_of_type(int spacecode)
3040 ScrArea *sa, *biggest= NULL;
3043 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
3044 if (spacecode==0 || sa->spacetype==spacecode) {
3045 int x= sa->v3->vec.x - sa->v1->vec.x;
3046 int y= sa->v3->vec.y - sa->v1->vec.y;
3047 int size= x*x + y*y;
3049 if (!biggest || size>bigsize) {
3059 ScrArea *find_biggest_area(void)
3061 return find_biggest_area_of_type(0);
3064 static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
3071 /* select connected, only in the right direction */
3072 /* 'dir' is the direction of EDGE */
3074 if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
3077 sv= sc->vertbase.first;
3087 while(oneselected) {
3088 se= sc->edgebase.first;
3091 if(se->v1->flag + se->v2->flag==1) {
3092 if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
3093 se->v1->flag= se->v2->flag= 1;
3096 if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
3097 se->v1->flag= se->v2->flag= 1;
3106 void test_scale_screen(bScreen *sc)
3107 /* test if screen vertices should be scaled */
3108 /* also check offset */
3114 float facx, facy, tempf, min[2], max[2];
3116 sc->startx= prefstax;
3117 sc->starty= prefstay;
3118 sc->endx= prefstax+prefsizx-1;
3119 sc->endy= prefstay+prefsizy-1;
3121 /* calculate size */
3122 sv= sc->vertbase.first;
3123 min[0]= min[1]= 0.0;
3127 min[0]= MIN2(min[0], sv->vec.x);
3128 min[1]= MIN2(min[1], sv->vec.y);
3129 max[0]= MAX2(max[0], sv->vec.x);
3130 max[1]= MAX2(max[1], sv->vec.y);
3134 /* always make 0.0 left under */
3135 sv= sc->vertbase.first;
3137 sv->vec.x -= min[0];
3138 sv->vec.y -= min[1];
3143 sc->sizex= max[0]-min[0];
3144 sc->sizey= max[1]-min[1];
3146 if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
3148 facx/= (float)sc->sizex;
3150 facy/= (float)sc->sizey;
3152 /* make sure it fits! */
3153 sv= sc->vertbase.first;
3155 tempf= ((float)sv->vec.x)*facx;
3156 sv->vec.x= (short)(tempf+0.5);
3157 sv->vec.x+= AREAGRID-1;
3158 sv->vec.x-= (sv->vec.x % AREAGRID);
3160 CLAMP(sv->vec.x, 0, prefsizx);
3162 tempf= ((float)sv->vec.y )*facy;
3163 sv->vec.y= (short)(tempf+0.5);
3164 sv->vec.y+= AREAGRID-1;
3165 sv->vec.y-= (sv->vec.y % AREAGRID);
3167 CLAMP(sv->vec.y, 0, prefsizy);
3172 sc->sizex= prefsizx;
3173 sc->sizey= prefsizy;
3176 /* test for collapsed areas. This could happen in some blender version... */
3177 sa= sc->areabase.first;
3180 if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
3182 BLI_remlink(&sc->areabase, sa);
3188 /* make each window at least HEADERY high */
3189 sa= sc->areabase.first;
3192 if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
3194 se= screen_findedge(sc, sa->v4, sa->v1);
3195 if(se && sa->v1!=sa->v2 ) {
3196 select_connected_scredge(sc, se);
3198 /* all selected vertices get the right offset */
3199 yval= sa->v2->vec.y-HEADERY;
3200 sv= sc->vertbase.first;
3202 /* if is a collapsed area */
3203 if(sv!=sa->v2 && sv!=sa->v3) {
3204 if(sv->flag) sv->vec.y= yval;
3216 static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
3219 sdrawXORline(start, dist, end, dist);
3220 sdrawXORline(start, dist+1, end, dist+1);
3222 sdrawXORline(dist, start, dist, end);
3223 sdrawXORline(dist+1, start, dist+1, end);
3227 static void moveareas(ScrEdge *edge)
3232 short edge_start, edge_end, edge_position;
3233 short bigger, smaller, headery, areaminy;
3237 if(edge->border) return;
3239 dir= scredge_is_horizontal(edge)?'h':'v';
3241 select_connected_scredge(G.curscreen, edge);
3243 edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
3246 for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
3249 edge_start= MIN2(edge_start, v1->vec.x);
3250 edge_end= MAX2(edge_end, v1->vec.x);
3252 edge_start= MIN2(edge_start, v1->vec.y);
3253 edge_end= MAX2(edge_end, v1->vec.y);
3258 /* now all verices with 'flag==1' are the ones that can be moved. */
3259 /* we check all areas and test for free space with MINSIZE */
3260 bigger= smaller= 10000;
3261 sa= G.curscreen->areabase.first;
3263 if(dir=='h') { /* if top or down edge selected, test height */
3264 if(sa->headertype) {
3270 areaminy= AREAMINY; /*areaminy= EDGEWIDTH;*/
3273 if(sa->v1->flag && sa->v4->flag) {
3275 if(sa->v2->vec.y==G.curscreen->sizey-1) /* top edge */
3276 y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
3278 y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
3279 bigger= MIN2(bigger, y1);
3281 else if(sa->v2->flag && sa->v3->flag) {
3283 if(sa->v1->vec.y==0) /* bottom edge */
3284 y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
3286 y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
3287 smaller= MIN2(smaller, y1);
3290 else { /* if left or right edge selected, test width */
3291 if(sa->v1->flag && sa->v2->flag) {
3292 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
3293 bigger= MIN2(bigger, x1);
3295 else if(sa->v3->flag && sa->v4->flag) {
3296 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
3297 smaller= MIN2(smaller, x1);
3303 mywinset(G.curscreen->mainwin);
3305 glReadBuffer(GL_FRONT);
3306 glDrawBuffer(GL_FRONT);
3309 getmouseco_sc(mvalo);
3310 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
3314 unsigned short event= extern_qread(&val);
3316 if (event==MOUSEY) {
3319 getmouseco_sc(mval);
3321 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
3323 delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
3324 delta= CLAMPIS(delta, -smaller, bigger);
3325 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
3328 else if (event==LEFTMOUSE) {
3332 if (ELEM(event, ESCKEY, RIGHTMOUSE))
3334 else if (ELEM(event, SPACEKEY, RETKEY))
3337 else BIF_wait_for_statechange();
3340 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
3342 glReadBuffer(GL_BACK);