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...
40 #include "BLI_winstuff.h"
50 #include "MEM_guardedalloc.h"
56 #include "BLI_blenlib.h"
57 #include "BLI_arithb.h"
59 #include "IMB_imbuf_types.h"
60 #include "IMB_imbuf.h"
62 #include "DNA_action_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_screen_types.h"
65 #include "DNA_space_types.h"
66 #include "DNA_sound_types.h"
67 #include "DNA_view3d_types.h"
68 #include "DNA_userdef_types.h"
70 #include "BLO_writefile.h"
72 #include "BKE_utildefines.h"
73 #include "BKE_global.h"
74 #include "BKE_library.h"
76 #include "BKE_blender.h"
77 #include "BKE_screen.h"
79 #include "BIF_editsound.h"
80 #include "BIF_glutil.h"
82 #include "BIF_graphics.h"
83 #include "BIF_interface.h"
84 #include "BIF_mainqueue.h"
85 #include "BIF_mywindow.h"
86 #include "BIF_renderwin.h"
87 #include "BIF_screen.h"
88 #include "BIF_space.h"
89 #include "BIF_toets.h"
90 #include "BIF_toolbox.h"
91 #include "BIF_usiblender.h"
92 #include "BIF_keyval.h"
95 #include "BSE_filesel.h"
96 #include "BSE_headerbuttons.h"
99 #include "interface.h"
100 #include "mydevice.h"
108 * - LET OP DE EDGES, VERTICES ERVAN MOETEN IN VOLGORDE
109 (laagste pointer eerst). Anders onvoorspelbare effecten!
110 * - probleem: flags zijn nog niet echt netjes. Altijd na gebruik
114 static void testareas(void);
115 static void area_autoplayscreen(void);
116 static void wait_for_event(void);
118 /* ********* Globals *********** */
120 static Window *mainwin= NULL;
121 static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
122 static short dodrawscreen= 0;
123 static ScrArea *areawinar[MAXWIN];
124 static ScrArea *g_activearea= NULL;
125 short winqueue_break= 0;
128 /**********************************************************************/
130 static void screen_set_cursor(bScreen *sc)
133 ScrArea *sa= areawinar[sc->winakt];
135 set_cursor(sa->cursor);
137 set_cursor(CURSOR_STD);
141 void waitcursor(int val)
144 set_cursor(CURSOR_WAIT);
146 screen_set_cursor(G.curscreen);
150 static int choose_cursor(ScrArea *sa)
152 if (sa->spacetype==SPACE_VIEW3D) {
153 if(G.obedit) return CURSOR_EDIT;
154 else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
155 else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
156 else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
157 else return CURSOR_STD;
163 void wich_cursor(ScrArea *sa)
165 sa->cursor= choose_cursor(sa);
167 screen_set_cursor(G.curscreen);
171 void setcursor_space(int spacetype, short cur)
176 for (sc= G.main->screen.first; sc; sc= sc->id.next)
177 for (sa= sc->areabase.first; sa; sa= sa->next)
178 if(sa->spacetype==spacetype)
181 screen_set_cursor(G.curscreen);
185 /* ********* IN/OUT ************* */
187 void getmouseco_sc(short *mval) /* screen coordinaten */
192 void getmouseco_areawin(short *mval) /* interne area coordinaten */
196 if(g_activearea && g_activearea->win) {
197 mval[0]-= g_activearea->winrct.xmin;
198 mval[1]-= g_activearea->winrct.ymin;
202 void getmouseco_headwin(short *mval) /* interne area coordinaten */
206 if(g_activearea && g_activearea->headwin) {
207 mval[0]-= g_activearea->headrct.xmin;
208 mval[1]-= g_activearea->headrct.ymin;
212 /* *********** STUFF ************** */
214 static int scredge_is_horizontal(ScrEdge *se)
216 return (se->v1->vec.y == se->v2->vec.y);
219 static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
223 for (se= sc->edgebase.first; se; se= se->next) {
224 if (scredge_is_horizontal(se)) {
225 if (abs(mval[1]-se->v1->vec.y)<=EDGEWIDTH2 &&
226 abs(mval[0]-se->v1->vec.x)<=abs(se->v2->vec.x-se->v1->vec.x))
229 if (abs(mval[0]-se->v1->vec.x)<=EDGEWIDTH2 &&
230 abs(mval[1]-se->v1->vec.y)<=abs(se->v2->vec.y-se->v1->vec.y))
238 void areawinset(short win)
241 curarea= areawinar[win];
243 printf("error in areawinar %d ,areawinset\n", win);
247 switch(curarea->spacetype) {
249 G.vd= curarea->spacedata.first;
252 if(G.sipo != curarea->spacedata.first) allqueue(REDRAWBUTSANIM, 0);
253 G.sipo= curarea->spacedata.first;
257 G.buts= curarea->spacedata.first;
261 SpaceSeq *sseq= curarea->spacedata.first;
266 G.soops= curarea->spacedata.first;
267 G.v2d= &G.soops->v2d;
270 G.sima= curarea->spacedata.first;
273 G.ssound= curarea->spacedata.first;
274 G.v2d= &G.ssound->v2d;
277 G.saction= curarea->spacedata.first;
278 G.v2d= &G.saction->v2d;
281 G.snla= curarea->spacedata.first;
289 if(win) mywinset(win);
292 void headerbox(int selcol, int width)
294 if(selcol) glClearColor(.75, .75, .75, 0.0);
295 else glClearColor(.65, .65, .65, 0.0);
297 glClear(GL_COLOR_BUFFER_BIT);
300 sdrawbox(0, 0, width, HEADERY);
302 glColor3ub(220, 220, 220);
303 sdrawline(0, HEADERY-1, width, HEADERY-1);
305 glColor3ub(176, 176, 176);
306 sdrawline(0, HEADERY-2, width, HEADERY-2);
308 glColor3ub(128, 128, 128);
309 sdrawline(0, 2, width, 2);
311 glColor3ub(64, 64, 64);
312 sdrawline(0, 1, width, 1);
315 sdrawline(0, 0, width, 0);
318 int area_is_active_area(ScrArea *area)
320 return (g_activearea && area==g_activearea);
323 void scrarea_do_headdraw(ScrArea *area)
325 areawinset(area->headwin);
327 headerbox(area_is_active_area(area), area->winx+100);
329 switch(area->spacetype) {
330 case SPACE_FILE: file_buttons(); break;
331 case SPACE_INFO: info_buttons(); break;
332 case SPACE_VIEW3D: view3d_buttons(); break;
333 case SPACE_IPO: ipo_buttons(); break;
334 case SPACE_BUTS: buts_buttons(); break;
335 case SPACE_SEQ: seq_buttons(); break;
336 case SPACE_IMAGE: image_buttons(); break;
337 case SPACE_IMASEL: imasel_buttons(); break;
338 case SPACE_OOPS: oops_buttons(); break;
339 case SPACE_TEXT: text_buttons(); break;
340 case SPACE_SOUND: sound_buttons(); break;
341 case SPACE_ACTION: action_buttons(); break;
342 case SPACE_NLA: nla_buttons(); break;
345 area->head_swap= WIN_BACK_OK;
347 void scrarea_do_headchange(ScrArea *area)
349 float ofs= area->headbutofs;
351 if (area->headertype==HEADERDOWN) {
352 bwin_ortho2(area->headwin, 0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, +0.6, area->headrct.ymax-area->headrct.ymin+0.6);
354 bwin_ortho2(area->headwin, -0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, -0.5, area->headrct.ymax-area->headrct.ymin-0.5);
359 static void openheadwin(ScrArea *sa);
360 static void closeheadwin(ScrArea *sa);
362 static void scrarea_change_headertype(ScrArea *sa, int newtype)
364 sa->headertype= newtype;
368 uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
381 static void headmenu(ScrArea *sa)
383 short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
386 scrarea_change_headertype(sa, val);
390 static void addqueue_ext(short win, unsigned short event, short val, char ascii)
392 if (win<4 || !areawinar[win]) {
393 printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
395 bwin_qadd(win, event, val, ascii);
399 void addqueue(short win, unsigned short event, short val)
401 addqueue_ext(win, event, val, 0);
404 void scrarea_queue_winredraw(ScrArea *area)
406 addqueue(area->win, REDRAW, 1);
408 void scrarea_queue_headredraw(ScrArea *area)
410 if (area->headwin) addqueue(area->headwin, REDRAW, 1);
412 void scrarea_queue_redraw(ScrArea *area)
414 scrarea_queue_winredraw(area);
415 scrarea_queue_headredraw(area);
418 static void scrollheader(ScrArea *area);
419 static void scrarea_dispatch_header_events(ScrArea *sa)
422 short do_redraw=0, do_change=0;
424 areawinset(sa->headwin);
426 while(bwin_qtest(sa->headwin)) {
429 unsigned short event= bwin_qread(sa->headwin, &val, &ascii);
432 if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
436 do_headerbuttons(val);
440 if (G.qual & LR_CTRLKEY) {
441 window_lower(mainwin);
443 window_raise(mainwin);
462 if (winqueue_break == 0) {
463 scrarea_do_winhandle(sa, event, val, ascii);
464 if (winqueue_break == 0) areawinset(sa->headwin);
468 if(winqueue_break) return;
472 /* test: bestaat window nog */
473 tempsa= areawinar[sa->headwin];
474 if(tempsa==0) return;
476 /* dit onderscheid loopt niet lekker... */
477 if(do_change) scrarea_do_headchange(sa);
478 if(do_redraw) scrarea_do_headdraw(sa);
481 static void scrarea_dispatch_events(ScrArea *sa)
484 short do_redraw=0, do_change=0;
486 if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
488 while(bwin_qtest(sa->win)) {
491 unsigned short event= bwin_qread(sa->win, &val, &ascii);
496 else if(event==CHANGED) {
502 scrarea_do_winhandle(sa, event, val, ascii);
505 if(winqueue_break) return;
508 /* test: bestaat window nog */
509 tempsa= areawinar[sa->win];
510 if(tempsa==0) return;
512 if (do_change || do_redraw) {
515 scrarea_do_winchange(curarea);
517 scrarea_do_windraw(curarea);
528 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
529 scrarea_queue_winredraw(sa);
530 sa->win_swap &= ~WIN_FRONT_OK;
532 scrarea_queue_headredraw(sa);
533 sa->head_swap &= ~WIN_FRONT_OK;
537 int is_allowed_to_change_screen(bScreen *new)
539 /* niet als curscreen is full
540 * niet als obedit && old->scene!=new->scene
544 if(G.curscreen->full != SCREENNORMAL) return 0;
545 if(curarea->full) return 0;
547 if(G.curscreen->scene!=new->scene) return 0;
552 void splash(void *data, int datasize, char *string)
558 bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
563 mywinset(G.curscreen->mainwin);
570 maxy = MIN2(bbuf->y, 18);
572 for (y = 0; y < maxy; y++) {
573 for (x = 0; x < bbuf->x; x++) {
579 glDrawBuffer(GL_FRONT);
582 // this dims the whole screen a bit. I didn't like it afterall
584 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
585 glColor4f(0.0,0.0,0.0,0.3);
586 glRecti(0, 0, G.curscreen->sizex, G.curscreen->sizey);
590 glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);
591 glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
597 if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
598 if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
601 width= BMF_GetStringWidth(font, string);
604 glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
605 BMF_DrawString(font, string);
609 glDrawBuffer(GL_BACK);
613 // flush input buffers ....
614 // this might break some things
617 BIF_wait_for_statechange();
627 mainqenter(DRAWEDGES, 1);
631 static void moveareas(ScrEdge *edge);
632 static void joinarea(ScrArea *sa, ScrEdge *onedge);
633 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
635 static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val) {
637 // don't allow users to edit full screens
638 if (actarea && actarea->full) {
642 if (evt==LEFTMOUSE) {
644 } else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
647 if (!actarea->headertype) {
648 edgeop= pupmenu("Split Area|Join Areas|Add header");
650 edgeop= pupmenu("Split Area|Join Areas|No header");
654 splitarea_interactive(actarea, actedge);
655 } else if (edgeop==2) {
656 joinarea(actarea, actedge);
657 } else if (edgeop==3) {
658 scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
666 void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
667 void test_scale_screen(bScreen *);
669 static void resize_screens(int x, int y, int w, int h) {
675 test_scale_screen(G.curscreen);
679 static void init_mainwin(void)
681 int orx, ory, sizex, sizey;
683 glEnable(GL_SCISSOR_TEST);
685 window_get_position(mainwin, &orx, &ory);
686 window_get_size(mainwin, &sizex, &sizey);
688 /* XXX, temporary stupid fix for minimize at windows */
689 if (!sizex && !sizey) {
693 mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
694 resize_screens(orx, ory, sizex, sizey);
699 static short afterqueue[MAXQUEUE][3];
700 static int nafterqitems= 0;
702 void addafterqueue(short win, unsigned short evt, short val)
704 if (nafterqitems<MAXQUEUE) {
705 afterqueue[nafterqitems][0]= win;
706 afterqueue[nafterqitems][1]= evt;
707 afterqueue[nafterqitems][2]= val;
712 static void append_afterqueue(void)
714 while (nafterqitems) {
715 short win= afterqueue[nafterqitems-1][0];
716 unsigned short evt= afterqueue[nafterqitems-1][1];
717 short val= afterqueue[nafterqitems-1][2];
719 addqueue(win, evt, val);
725 static char ext_load_str[256]= {0, 0};
726 void add_readfile_event(char *filename)
728 mainqenter(LOAD_FILE, 1);
729 strcpy(ext_load_str, filename);
730 BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
733 static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
735 static void flush_extqd_events(void) {
736 if (ext_inputchange) {
737 mainqenter(INPUTCHANGE, ext_inputchange);
738 } else if (ext_reshape) {
739 mainqenter(RESHAPE, ext_redraw);
740 } else if (ext_redraw) {
741 mainqenter(REDRAW, ext_redraw);
742 } else if (ext_mousemove) {
745 getmouseco_sc(mouse);
747 mainqenter(MOUSEX, mouse[0]);
748 mainqenter(MOUSEY, mouse[1]);
751 ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
754 unsigned short qtest(void)
757 winlay_process_events(0);
763 /* return true if events are waiting anywhere */
768 if (nafterqitems || qtest()) return 1;
770 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
771 if (bwin_qtest(sa->win)) return 1;
772 if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
778 static void wait_for_event(void)
780 while (!mainqtest()) {
781 winlay_process_events(1);
785 unsigned short screen_qread(short *val, char *ascii)
787 unsigned short event;
791 event= mainqread(val, ascii);
793 if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
794 if(*val) G.qual |= LR_SHIFTKEY;
795 else G.qual &= ~LR_SHIFTKEY;
797 else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
798 if(*val) G.qual |= LR_ALTKEY;
799 else G.qual &= ~LR_ALTKEY;
801 else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
802 if(*val) G.qual |= LR_CTRLKEY;
803 else G.qual &= ~LR_CTRLKEY;
809 unsigned short extern_qread_ext(short *val, char *ascii)
811 /* bewaart de laatste INPUTCHANGE en de laatste REDRAW */
812 unsigned short event;
814 event= screen_qread(val, ascii);
815 if(event==RESHAPE) ext_reshape= *val;
816 else if(event==REDRAW) ext_redraw= *val;
817 else if(event==INPUTCHANGE) ext_inputchange= *val;
818 else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
819 else if((G.qual & LR_CTRLKEY) && event==F3KEY) {
825 unsigned short extern_qread(short *val)
828 return extern_qread_ext(val, &ascii);
831 void reset_autosave(void) {
832 window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
835 static void screen_dispatch_events(void) {
836 int events_remaining= 1;
839 while (events_remaining) {
843 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
844 /* bewust eerst header afhandelen, dan rest. Header is soms init */
845 if (sa->headwin && bwin_qtest(sa->headwin)) {
846 scrarea_dispatch_header_events(sa);
849 if (winqueue_break) break;
851 if (bwin_qtest(sa->win)) {
852 scrarea_dispatch_events(sa);
855 if (winqueue_break) break;
858 if (winqueue_break) break;
866 screen_swapbuffers();
869 static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval)
873 for (sa= sc->areabase.first; sa; sa= sa->next)
874 if (BLI_in_rcti(&sa->totrct, mval[0], mval[1]))
880 void screenmain(void)
885 unsigned short event;
889 flush_extqd_events();
890 if (nafterqitems && !qtest()) {
894 event= screen_qread(&val, &ascii);
897 window_make_active(mainwin);
899 if (event==INPUTCHANGE) {
909 newactarea= screen_find_area_for_pt(G.curscreen, mval);
912 if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
913 newactwin= newactarea->headwin;
915 newactwin= newactarea->win;
921 if (newactarea && (newactarea != g_activearea)) {
922 if (g_activearea) scrarea_queue_headredraw(g_activearea);
923 scrarea_queue_headredraw(newactarea);
924 set_cursor(newactarea->cursor);
925 g_activearea= newactarea;
928 G.curscreen->winakt= newactwin;
929 if (G.curscreen->winakt) {
930 areawinset(G.curscreen->winakt);
931 set_cursor(choose_cursor(g_activearea));
935 scrarea_queue_headredraw(g_activearea);
938 G.curscreen->winakt= 0;
942 if (event==WINCLOSE) {
945 else if (event==DRAWEDGES) {
948 else if (event==RESHAPE) {
953 else if (event==REDRAW) {
957 else if (event==AUTOSAVE_FILE) {
958 BIF_write_autosave();
960 else if (event==LOAD_FILE) {
961 BIF_read_file(ext_load_str);
962 sound_initialize_sounds();
971 else if (!G.curscreen->winakt) {
976 actedge= screen_find_active_scredge(G.curscreen, mval);
979 if (scredge_is_horizontal(actedge)) {
980 set_cursor(CURSOR_Y_MOVE);
982 set_cursor(CURSOR_X_MOVE);
985 screen_edge_edit_event(g_activearea, actedge, event, val);
987 set_cursor(CURSOR_STD);
992 else if (event==QKEY) {
993 if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
995 if(val && okee("QUIT BLENDER")) exit_usiblender();
999 else if (event==ZKEY) {
1000 if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
1001 extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
1003 int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
1006 case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
1007 case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
1008 case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
1009 case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
1010 case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
1013 g_activearea->head_swap= 0;
1014 g_activearea->win_swap= 0;
1021 else if (event==SPACEKEY) {
1022 if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
1028 else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
1029 if(val && (G.qual & LR_CTRLKEY)) {
1030 bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
1031 if(is_allowed_to_change_screen(sc)) setscreen(sc);
1036 else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
1037 if(val && (G.qual & LR_CTRLKEY)) {
1044 if (towin && event) {
1045 if (blenderqread(event, val))
1046 addqueue_ext(G.curscreen->winakt, event, val, ascii);
1049 /* only process subwindow queue's once the
1050 * main queue has been emptyied.
1053 if (event==0 || event==EXECUTE) {
1054 screen_dispatch_events();
1057 /* Bizar hack. The event queue has mutated... */
1058 if ( (firsttime) && (event == 0) ) {
1059 if (G.fileflags & G_FILE_AUTOPLAY) {
1060 // SET AUTOPLAY in G.flags for
1063 G.flags |= G_FLAGS_AUTOPLAY;
1064 area_autoplayscreen();
1066 // Let The Games Begin
1067 // fake a 'p' keypress
1069 mainqenter(PKEY, 1);
1071 extern char datatoc_splash_jpg[];
1072 extern int datatoc_splash_jpg_size;
1074 if (! ((G.main->versionfile >= G.version)
1076 splash((void *)datatoc_splash_jpg,
1077 datatoc_splash_jpg_size, NULL);
1085 void mainwindow_raise(void) {
1086 window_raise(mainwin);
1088 void mainwindow_make_active(void) {
1089 window_make_active(mainwin);
1091 void mainwindow_close(void) {
1092 window_destroy(mainwin);
1096 /* ********* AREAS ************* */
1098 void setprefsize(int stax, int stay, int sizx, int sizy)
1100 int scrwidth, scrheight;
1102 winlay_get_screensize(&scrwidth, &scrheight);
1106 if(sizx<320) sizx= 320;
1107 if(sizy<256) sizy= 256;
1109 if(stax+sizx>scrwidth) sizx= scrwidth-stax;
1110 if(stay+sizy>scrheight) sizy= scrheight-stay;
1111 if(sizx<320 || sizy<256) {
1112 printf("ERROR: illegal prefsize\n");
1125 static ScrVert *screen_addvert(bScreen *sc, short x, short y)
1127 ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
1131 BLI_addtail(&sc->vertbase, sv);
1135 static void sortscrvert(ScrVert **v1, ScrVert **v2)
1139 if ((long)*v1 > (long)*v2) {
1146 static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1148 ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
1150 sortscrvert(&v1, &v2);
1154 BLI_addtail(&sc->edgebase, se);
1158 static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1162 sortscrvert(&v1, &v2);
1163 for (se= sc->edgebase.first; se; se= se->next)
1164 if(se->v1==v1 && se->v2==v2)
1170 static void removedouble_scrverts(void)
1176 verg= G.curscreen->vertbase.first;
1178 if(verg->newv==0) { /* !!! */
1181 if(v1->newv==0) { /* !?! */
1182 if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
1183 /* printf("doublevert\n"); */
1193 /* vervang pointers in edges en vlakken */
1194 se= G.curscreen->edgebase.first;
1196 if(se->v1->newv) se->v1= se->v1->newv;
1197 if(se->v2->newv) se->v2= se->v2->newv;
1198 /* edges zijn veranderd: dus.... */
1199 sortscrvert(&(se->v1), &(se->v2));
1202 sa= G.curscreen->areabase.first;
1204 if(sa->v1->newv) sa->v1= sa->v1->newv;
1205 if(sa->v2->newv) sa->v2= sa->v2->newv;
1206 if(sa->v3->newv) sa->v3= sa->v3->newv;
1207 if(sa->v4->newv) sa->v4= sa->v4->newv;
1212 verg= G.curscreen->vertbase.first;
1216 BLI_remlink(&G.curscreen->vertbase, verg);
1224 static void removenotused_scrverts(void)
1229 /* ga ervan uit dat de edges goed zijn */
1231 se= G.curscreen->edgebase.first;
1238 sv= G.curscreen->vertbase.first;
1242 BLI_remlink(&G.curscreen->vertbase, sv);
1250 static void removedouble_scredges(void)
1252 ScrEdge *verg, *se, *sn;
1255 verg= G.curscreen->edgebase.first;
1260 if(verg->v1==se->v1 && verg->v2==se->v2) {
1261 BLI_remlink(&G.curscreen->edgebase, se);
1270 static void removenotused_scredges(void)
1276 /* zet flag als edge gebruikt wordt in area */
1277 sa= G.curscreen->areabase.first;
1279 se= screen_findedge(G.curscreen, sa->v1, sa->v2);
1280 if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
1282 se= screen_findedge(G.curscreen, sa->v2, sa->v3);
1283 if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
1285 se= screen_findedge(G.curscreen, sa->v3, sa->v4);
1286 if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
1288 se= screen_findedge(G.curscreen, sa->v4, sa->v1);
1289 if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
1294 se= G.curscreen->edgebase.first;
1298 BLI_remlink(&G.curscreen->edgebase, se);
1306 void calc_arearcts(ScrArea *sa)
1309 if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+EDGEWIDTH2+1;
1310 else sa->totrct.xmin= sa->v1->vec.x;
1311 if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-EDGEWIDTH2-1;
1312 else sa->totrct.xmax= sa->v4->vec.x;
1314 if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+EDGEWIDTH2+1;
1315 else sa->totrct.ymin= sa->v1->vec.y;
1316 if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-EDGEWIDTH2-1;
1317 else sa->totrct.ymax= sa->v2->vec.y;
1319 sa->winrct= sa->totrct;
1320 if(sa->headertype) {
1321 sa->headrct= sa->totrct;
1322 if(sa->headertype==HEADERDOWN) {
1323 sa->headrct.ymax= sa->headrct.ymin+HEADERY-1;
1324 sa->winrct.ymin= sa->headrct.ymax+1;
1326 else if(sa->headertype==HEADERTOP) {
1327 sa->headrct.ymin= sa->headrct.ymax-HEADERY+1;
1328 sa->winrct.ymax= sa->headrct.ymin-1;
1331 if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
1333 /* als speedup voor berekeningen */
1334 sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
1335 sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
1338 static void openheadwin(ScrArea *sa)
1340 sa->headwin= myswinopen(G.curscreen->mainwin,
1341 sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1343 glMatrixMode(GL_MODELVIEW);
1345 areawinar[sa->headwin]= sa; /* anders doet addqueue het niet */
1346 addqueue(sa->headwin, CHANGED, 1);
1349 static void openareawin(ScrArea *sa)
1351 sa->win= myswinopen(G.curscreen->mainwin,
1352 sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1354 areawinar[sa->win]= sa; /* anders doet addqueue het niet */
1355 addqueue(sa->win, CHANGED, 1);
1358 static void closeheadwin(ScrArea *sa)
1360 if(sa->headwin) mywinclose(sa->headwin);
1364 static void closeareawin(ScrArea *sa)
1366 uiFreeBlocksWin(&sa->uiblocks, sa->win);
1368 if(sa->win) mywinclose(sa->win);
1372 static void del_area(ScrArea *sa)
1377 freespacelist(&sa->spacedata);
1379 uiFreeBlocks(&sa->uiblocks);
1381 if(sa==curarea) curarea= 0;
1382 if(sa==g_activearea) g_activearea= 0;
1385 static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
1387 sa1->headertype= sa2->headertype;
1388 sa1->spacetype= sa2->spacetype;
1389 Mat4CpyMat4(sa1->winmat, sa2->winmat);
1391 freespacelist(&sa1->spacedata);
1393 duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
1396 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
1398 ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
1399 sa->cursor= CURSOR_STD;
1404 sa->headertype= headertype;
1405 sa->spacetype= spacetype;
1409 if (sa->headertype) openheadwin(sa);
1412 BLI_addtail(&sc->areabase, sa);
1416 static int rcti_eq(rcti *a, rcti *b) {
1417 return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
1418 (a->ymin==b->ymin && a->ymax==b->ymax));
1421 static void testareas(void)
1425 /* testen of header er moet zijn, of weg moet, of verplaatst */
1426 /* testen of window er moet zijn, of weg moet, of verplaatst */
1428 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1429 rcti oldhr= sa->headrct;
1430 rcti oldwr= sa->winrct;
1436 if (!rcti_eq(&oldhr, &sa->headrct)) {
1437 mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1438 addqueue(sa->headwin, CHANGED, 1);
1441 if(sa->headbutlen<sa->winx) {
1443 addqueue(sa->headwin, CHANGED, 1);
1445 else if(sa->headbutofs+sa->winx > sa->headbutlen) {
1446 sa->headbutofs= sa->headbutlen-sa->winx;
1447 addqueue(sa->headwin, CHANGED, 1);
1451 if (!rcti_eq(&oldwr, &sa->winrct)) {
1452 mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1453 addqueue(sa->win, CHANGED, 1);
1457 /* remake global windowarray */
1458 memset(areawinar, 0, sizeof(void *)*MAXWIN);
1459 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1460 areawinar[sa->headwin]= sa;
1461 areawinar[sa->win]= sa;
1464 /* test of winakt in orde is */
1465 if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
1468 static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
1470 /* test of edge in area ligt, zo niet,
1471 vind een area die 'm wel heeft */
1473 ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
1476 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1477 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1478 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1479 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1481 if(se1!=se && se2!=se && se3!=se && se4!=se) {
1483 sa= G.curscreen->areabase.first;
1485 /* een beetje optimaliseren? */
1486 if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
1487 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1488 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1489 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1490 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1491 if(se1==se || se2==se || se3==se || se4==se) return sa;
1497 return sa; /* is keurig 0 als niet gevonden */
1500 ScrArea *closest_bigger_area(void)
1502 ScrArea *sa, *big=0;
1503 float cent[3], vec[3],len, len1, len2, len3, dist=1000;
1506 getmouseco_sc(mval);
1512 sa= G.curscreen->areabase.first;
1515 if(sa->winy>=curarea->winy) {
1517 /* mimimum van vier hoekpunten */
1518 vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
1519 len= VecLenf(vec, cent);
1520 vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
1521 len1= VecLenf(vec, cent);
1522 vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
1523 len2= VecLenf(vec, cent);
1524 vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
1525 len3= VecLenf(vec, cent);
1527 len= MIN4(len, len1, len2, len3);
1530 vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
1531 vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
1533 len+= 0.5*VecLenf(vec, cent);
1536 len-= sa->winy+sa->winx;
1548 else return curarea;
1551 /* ************ SCREENBEHEER ************** */
1553 static int statechanged= 0;
1554 void BIF_wait_for_statechange(void)
1556 if (!statechanged) {
1557 /* Safety, don't wait more than 0.1 seconds */
1558 double stime= PIL_check_seconds_timer();
1559 while (!statechanged) {
1560 winlay_process_events(1);
1561 if ((PIL_check_seconds_timer()-stime)>0.1) break;
1566 void getmouse(short *mval)
1568 winlay_process_events(0);
1569 window_get_mouse(mainwin, mval);
1571 short get_qual(void)
1573 winlay_process_events(0);
1574 return window_get_qual(mainwin);
1576 short get_mbut(void)
1578 winlay_process_events(0);
1579 return window_get_mbut(mainwin);
1582 static unsigned short convert_for_nonumpad(unsigned short event)
1584 if (event>=ZEROKEY && event<=NINEKEY) {
1585 return event - ZEROKEY + PAD0;
1586 } else if (event==MINUSKEY) {
1588 } else if (event==EQUALKEY) {
1590 } else if (event==BACKSLASHKEY) {
1597 void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
1599 short qual= window_get_qual(win);
1603 if (U.flag&NONUMPAD) {
1604 evt= convert_for_nonumpad(evt);
1607 /* enforce some guarentees about ascii values... these should
1608 * be enforced in ghost probably - zr
1611 if (!val || !isprint(ascii) || (qual&~LR_SHIFTKEY)) {
1615 mainqenter_ext(evt, val, ascii);
1618 static bScreen *addscreen(char *name) /* gebruik de setprefsize() als je anders dan fullscreen wilt */
1620 /* deze functie zet de variabele G.curscreen
1621 * omdat alle hulpfuncties moeten weten welk screen
1624 ScrVert *sv1, *sv2, *sv3, *sv4;
1625 short startx, starty, endx, endy;
1627 sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
1633 winlay_get_screensize(&prefsizx, &prefsizy);
1638 endx= prefstax+prefsizx-1;
1639 endy= prefstay+prefsizy-1;
1641 sc->startx= startx; sc->starty= starty;
1642 sc->endx= endx; sc->endy= endy;
1643 sc->sizex= sc->endx-sc->startx+1;
1644 sc->sizey= sc->endy-sc->starty+1;
1649 mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
1651 printf("ERROR: Unable to open Blender window\n");
1655 window_set_handler(mainwin, add_to_mainqueue, NULL);
1659 glMatrixMode(GL_PROJECTION);
1661 myortho2(-0.5, sc->sizex-0.5, -0.5, sc->sizey-0.5);
1662 glMatrixMode(GL_MODELVIEW);
1665 glDrawBuffer(GL_FRONT);
1666 glClearColor(.45, .45, .45, 0.0);
1667 glClear(GL_COLOR_BUFFER_BIT);
1668 glDrawBuffer(GL_BACK);
1670 warp_pointer(sc->sizex/2, sc->sizey/2);
1672 mainqenter(REDRAW, 1);
1677 sv1= screen_addvert(sc, 0, 0);
1678 sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
1679 sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
1680 sv4= screen_addvert(sc, sc->sizex-1, 0);
1682 screen_addedge(sc, sv1, sv2);
1683 screen_addedge(sc, sv2, sv3);
1684 screen_addedge(sc, sv3, sv4);
1685 screen_addedge(sc, sv4, sv1);
1687 screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
1694 void setscreen(bScreen *sc)
1700 if(sc->full) { /* vind de bijhorende full */
1701 sc1= G.main->screen.first;
1703 sa= sc1->areabase.first;
1710 if(sc1==0) printf("setscreen error\n");
1713 /* G.curscreen de-activeren */
1714 if (G.curscreen && G.curscreen != sc) {
1715 sa= G.curscreen->areabase.first;
1717 if(sa->win) mywinclose(sa->win);
1719 if(sa->headwin) mywinclose(sa->headwin);
1722 uiFreeBlocks(&sa->uiblocks);
1728 if (G.curscreen != sc) {
1729 mywinset(sc->mainwin);
1734 for (sa= sc->areabase.first; sa; sa= sa->next) {
1736 /* if (sa->win || sa->headwin) */
1737 /* printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
1740 if (!sa->headwin && sa->headertype)
1744 /* recalculate winakt */
1745 getmouseco_sc(mval);
1747 test_scale_screen(sc);
1750 for (sa= sc->areabase.first; sa; sa= sa->next) {
1753 for (sl= sa->spacedata.first; sl; sl= sl->next) {
1756 if (sl->spacetype==SPACE_OOPS) {
1757 SpaceOops *soops= (SpaceOops*) sl;
1759 /* patch als deze in oude files zit */
1760 if (soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
1761 extern void init_v2d_oops(View2D*);
1762 init_v2d_oops(&soops->v2d);
1767 sa->cursor= CURSOR_STD;
1773 G.curscreen->winakt= 0;
1774 curarea= sc->areabase.first;
1776 mainqenter(DRAWEDGES, 1);
1777 dodrawscreen= 1; /* patch! even gets lost,,,? */
1779 winqueue_break= 1; /* overal uit de queue's gaan */
1782 static void splitarea(ScrArea *sa, char dir, float fac);
1784 void area_fullscreen(void) /* met curarea */
1786 /* deze funktie toggelt: als area full is wordt de parent weer zichtbaar */
1787 bScreen *sc, *oldscreen;
1788 ScrArea *newa, *old;
1789 short headertype, fulltype;
1792 sc= curarea->full; /* de oude screen */
1793 fulltype = sc->full;
1795 // refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
1798 if (fulltype != SCREENAUTOPLAY || (G.flags & G_FLAGS_AUTOPLAY) == 0) {
1801 /* vind oude area */
1802 old= sc->areabase.first;
1804 if(old->full) break;
1807 if(old==0) {error("something wrong in areafullscreen"); return;}
1809 if (fulltype == SCREENAUTOPLAY) {
1810 // in autoplay screens the headers are disabled by
1811 // default. So use the old headertype instead
1812 headertype = old->headertype;
1814 // normal fullscreen. Use current headertype
1815 headertype = curarea->headertype;
1818 copy_areadata(old, curarea);
1819 old->headertype = headertype;
1823 unlink_screen(G.curscreen);
1824 free_libblock(&G.main->screen, G.curscreen);
1832 /* is er maar 1 area? */
1833 if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
1834 if(curarea->spacetype==SPACE_INFO) return;
1836 G.curscreen->full = SCREENFULL;
1839 oldscreen= G.curscreen;
1840 sc= addscreen("temp"); /* deze zet G.curscreen */
1842 splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
1843 newa= sc->areabase.first;
1844 newspace(newa->next, SPACE_INFO);
1847 G.curscreen= oldscreen; /* moet voor setscreen */
1849 /* area kopieeren */
1850 copy_areadata(newa, curarea);
1852 curarea->full= oldscreen;
1853 newa->full= oldscreen;
1854 newa->next->full= oldscreen;
1861 static void area_autoplayscreen(void)
1863 bScreen *sc, *oldscreen;
1864 ScrArea *newa, *old, *sa;
1866 if (curarea->full) {
1870 if (curarea->full == NULL) {
1871 sa = G.curscreen->areabase.first;
1873 if (sa->spacetype == SPACE_VIEW3D) {
1880 areawinset(sa->win);
1881 G.curscreen->full = SCREENAUTOPLAY;
1884 oldscreen= G.curscreen;
1885 sc= addscreen("temp"); /* deze zet G.curscreen */
1887 newa= sc->areabase.first;
1890 G.curscreen= oldscreen; /* moet voor setscreen */
1892 /* copy area settings */
1893 copy_areadata(newa, curarea);
1894 newa->headertype= 0;
1896 curarea->full= oldscreen;
1897 newa->full= oldscreen;
1905 static void copy_screen(bScreen *to, bScreen *from)
1912 /* alles van to vrijgeven */
1914 winqueue_break= 1; /* overal uit queue's gaan */
1916 duplicatelist(&to->vertbase, &from->vertbase);
1917 duplicatelist(&to->edgebase, &from->edgebase);
1918 duplicatelist(&to->areabase, &from->areabase);
1920 s1= from->vertbase.first;
1921 s2= to->vertbase.first;
1927 se= to->edgebase.first;
1929 se->v1= se->v1->newv;
1930 se->v2= se->v2->newv;
1931 sortscrvert(&(se->v1), &(se->v2));
1935 sa= to->areabase.first;
1937 sa->v1= sa->v1->newv;
1938 sa->v2= sa->v2->newv;
1939 sa->v3= sa->v3->newv;
1940 sa->v4= sa->v4->newv;
1944 sa->uiblocks.first= sa->uiblocks.last= NULL;
1946 duplicatespacelist(sa, &lbase, &sa->spacedata);
1947 sa->spacedata= lbase;
1952 /* op nul zetten (nodig?) */
1953 s1= from->vertbase.first;
1960 void duplicate_screen(void)
1962 bScreen *sc, *oldscreen;
1964 if(G.curscreen->full != SCREENNORMAL) return;
1966 /* nieuw screen maken: */
1968 oldscreen= G.curscreen;
1969 sc= addscreen(oldscreen->id.name+2); /* deze zet G.curscreen */
1970 copy_screen(sc, oldscreen);
1972 G.curscreen= oldscreen;
1978 /* ************ END SCREENBEHEER ************** */
1979 /* ************ JOIN/SPLIT/MOVE ************** */
1981 static void joinarea(ScrArea *sa, ScrEdge *onedge)
1984 ScrArea *up=0, *down=0, *right=0, *left=0;
1988 sa= test_edge_area(sa, onedge);
1991 /* welke edges kunnen ermee? */
1992 /* vind richtingen met zelfde edge */
1993 sa2= G.curscreen->areabase.first;
1996 setest= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
1997 if(onedge==setest) right= sa2;
1998 setest= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
1999 if(onedge==setest) down= sa2;
2000 setest= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
2001 if(onedge==setest) left= sa2;
2002 setest= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
2003 if(onedge==setest) up= sa2;
2019 else if(up) sa2= up;
2020 else if(right) sa2= right;
2021 else if(down) sa2= down;
2026 /* nieuwe area is oude sa */
2030 screen_addedge(G.curscreen, sa->v2, sa->v3);
2031 screen_addedge(G.curscreen, sa->v1, sa->v4);
2036 screen_addedge(G.curscreen, sa->v1, sa->v2);
2037 screen_addedge(G.curscreen, sa->v3, sa->v4);
2039 else if(sa2==right) {
2042 screen_addedge(G.curscreen, sa->v2, sa->v3);
2043 screen_addedge(G.curscreen, sa->v1, sa->v4);
2045 else if(sa2==down) {
2048 screen_addedge(G.curscreen, sa->v1, sa->v2);
2049 screen_addedge(G.curscreen, sa->v3, sa->v4);
2052 /* edge en area weg */
2053 /* remlink(&G.curscreen->edgebase, setest); */
2054 /* freeN(setest); */
2056 BLI_remlink(&G.curscreen->areabase, sa2);
2059 removedouble_scredges();
2060 removenotused_scredges();
2061 removenotused_scrverts(); /* moet als laatste */
2064 mainqenter(DRAWEDGES, 1);
2065 /* test cursor en inputwindow */
2066 mainqenter(MOUSEY, -1);
2070 static short testsplitpoint(ScrArea *sa, char dir, float fac)
2071 /* return 0: geen split mogelijk */
2072 /* else return (integer) screencoordinaat splitpunt */
2076 /* area groot genoeg? */
2077 if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
2078 if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
2080 /* voor zekerheid */
2081 if(fac<0.0) fac= 0.0;
2082 if(fac>1.0) fac= 1.0;
2085 y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
2087 if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY+EDGEWIDTH2)
2088 y= sa->v2->vec.y- HEADERY-EDGEWIDTH2;
2090 else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY+EDGEWIDTH2)
2091 y= sa->v1->vec.y+ HEADERY+EDGEWIDTH2;
2093 else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
2094 else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
2095 else y-= (y % AREAGRID);
2100 x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
2101 if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
2102 else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
2103 else x-= (x % AREAGRID);
2109 static void splitarea(ScrArea *sa, char dir, float fac)
2118 split= testsplitpoint(sa, dir, fac);
2119 if(split==0) return;
2123 areawinset(sa->win);
2126 /* nieuwe vertices */
2127 sv1= screen_addvert(sc, sa->v1->vec.x, split);
2128 sv2= screen_addvert(sc, sa->v4->vec.x, split);
2131 screen_addedge(sc, sa->v1, sv1);
2132 screen_addedge(sc, sv1, sa->v2);
2133 screen_addedge(sc, sa->v3, sv2);
2134 screen_addedge(sc, sv2, sa->v4);
2135 screen_addedge(sc, sv1, sv2);
2137 /* nieuwe areas: boven */
2138 newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
2139 copy_areadata(newa, sa);
2147 /* nieuwe vertices */
2148 sv1= screen_addvert(sc, split, sa->v1->vec.y);
2149 sv2= screen_addvert(sc, split, sa->v2->vec.y);
2152 screen_addedge(sc, sa->v1, sv1);
2153 screen_addedge(sc, sv1, sa->v4);
2154 screen_addedge(sc, sa->v2, sv2);
2155 screen_addedge(sc, sv2, sa->v3);
2156 screen_addedge(sc, sv1, sv2);
2158 /* nieuwe areas: links */
2159 newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
2160 copy_areadata(newa, sa);
2167 /* dubbele vertices en edges verwijderen */
2168 removedouble_scrverts();
2169 removedouble_scredges();
2170 removenotused_scredges();
2172 mainqenter(DRAWEDGES, 1);
2173 dodrawscreen= 1; /* patch! even gets lost,,,? */
2177 static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
2179 int split= testsplitpoint(sa, dir, fac);
2183 glutil_draw_front_xor_line(sa->totrct.xmin, split, sa->totrct.xmax, split);
2184 glutil_draw_front_xor_line(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
2186 glutil_draw_front_xor_line(split, sa->totrct.ymin, split, sa->totrct.ymax);
2187 glutil_draw_front_xor_line(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
2192 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
2196 unsigned short event;
2197 short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
2200 if(sa->win==0) return;
2201 if(sa->full) return;
2203 dir= scredge_is_horizontal(onedge)?'v':'h';
2205 mywinset(G.curscreen->mainwin);
2206 /* hoort al goede matrix te hebben */
2208 /* rekening houden met grid en minsize */
2210 getmouseco_sc(mval);
2212 if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2214 scrarea_draw_splitpoint(sa, dir, fac);
2218 fac= mval[1]- (sa->v1->vec.y);
2219 fac/= sa->v2->vec.y- sa->v1->vec.y;
2221 fac= mval[0]- sa->v1->vec.x;
2222 fac/= sa->v4->vec.x- sa->v1->vec.x;
2225 split= testsplitpoint(sa, dir, fac);
2227 scrarea_draw_splitpoint(sa, dir, fac);
2237 event= extern_qread(&val);
2238 if(val && event==LEFTMOUSE) {
2240 fac= split- (sa->v1->vec.y);
2241 fac/= sa->v2->vec.y- sa->v1->vec.y;
2244 fac= split- sa->v1->vec.x;
2245 fac/= sa->v4->vec.x- sa->v1->vec.x;
2249 if(val && event==ESCKEY) {
2255 scrarea_draw_splitpoint(sa, dir, fac);
2259 splitarea(sa, dir, fac);
2260 mainqenter(DRAWEDGES, 1);
2261 dodrawscreen= 1; /* patch! even gets lost,,,? */
2265 View3D *find_biggest_view3d(void)
2267 ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
2270 return (View3D*) sa->spacedata.first;
2276 ScrArea *find_biggest_area_of_type(int spacecode)
2278 ScrArea *sa, *biggest= NULL;
2281 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2282 if (spacecode==0 || sa->spacetype==spacecode) {
2283 int x= sa->v3->vec.x - sa->v1->vec.x;
2284 int y= sa->v3->vec.y - sa->v1->vec.y;
2285 int size= x*x + y*y;
2287 if (!biggest || size>bigsize) {
2297 ScrArea *find_biggest_area(void)
2299 return find_biggest_area_of_type(0);
2302 static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
2309 /* select connected, alleen in de juiste richting */
2310 /* 'dir' is de richting van de EDGE */
2312 if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
2315 sv= sc->vertbase.first;
2325 while(oneselected) {
2326 se= sc->edgebase.first;
2329 if(se->v1->flag + se->v2->flag==1) {
2330 if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
2331 se->v1->flag= se->v2->flag= 1;
2334 if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
2335 se->v1->flag= se->v2->flag= 1;
2344 void test_scale_screen(bScreen *sc)
2345 /* testen of screenvertices vergroot/verkleind moeten worden */
2346 /* testen of offset nog klopt */
2352 float facx, facy, tempf, min[2], max[2];
2354 sc->startx= prefstax;
2355 sc->starty= prefstay;
2356 sc->endx= prefstax+prefsizx-1;
2357 sc->endy= prefstay+prefsizy-1;
2359 /* calculate size */
2360 sv= sc->vertbase.first;
2361 min[0]= min[1]= 0.0;
2365 min[0]= MIN2(min[0], sv->vec.x);
2366 min[1]= MIN2(min[1], sv->vec.y);
2367 max[0]= MAX2(max[0], sv->vec.x);
2368 max[1]= MAX2(max[1], sv->vec.y);
2372 /* always make 0.0 left under */
2373 sv= sc->vertbase.first;
2375 sv->vec.x -= min[0];
2376 sv->vec.y -= min[1];
2381 sc->sizex= max[0]-min[0];
2382 sc->sizey= max[1]-min[1];
2384 if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
2386 facx/= (float)sc->sizex;
2388 facy/= (float)sc->sizey;
2390 /* make sure it fits! */
2391 sv= sc->vertbase.first;
2393 tempf= ((float)sv->vec.x)*facx;
2394 sv->vec.x= (short)(tempf+0.5);
2395 sv->vec.x+= AREAGRID-1;
2396 sv->vec.x-= (sv->vec.x % AREAGRID);
2398 CLAMP(sv->vec.x, 0, prefsizx);
2400 tempf= ((float)sv->vec.y )*facy;
2401 sv->vec.y= (short)(tempf+0.5);
2402 sv->vec.y+= AREAGRID-1;
2403 sv->vec.y-= (sv->vec.y % AREAGRID);
2405 CLAMP(sv->vec.y, 0, prefsizy);
2410 sc->sizex= prefsizx;
2411 sc->sizey= prefsizy;
2414 /* test for collapsed areas. This could happen in some blender version... */
2415 sa= sc->areabase.first;
2418 if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
2420 BLI_remlink(&sc->areabase, sa);
2426 /* make each window at least HEADERY high */
2428 sa= sc->areabase.first;
2431 if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
2433 se= screen_findedge(sc, sa->v4, sa->v1);
2434 if(se && sa->v1!=sa->v2 ) {
2435 select_connected_scredge(sc, se);
2437 /* all selected vertices get the right offset */
2438 yval= sa->v2->vec.y-HEADERY;
2439 sv= sc->vertbase.first;
2441 /* if is a collapsed area */
2442 if(sv!=sa->v2 && sv!=sa->v3) {
2443 if(sv->flag) sv->vec.y= yval;
2455 static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
2458 glutil_draw_front_xor_line(start, dist, end, dist);
2459 glutil_draw_front_xor_line(start, dist+1, end, dist+1);
2461 glutil_draw_front_xor_line(dist, start, dist, end);
2462 glutil_draw_front_xor_line(dist+1, start, dist+1, end);
2466 static void moveareas(ScrEdge *edge)
2471 short edge_start, edge_end, edge_position;
2472 short bigger, smaller, headery, areaminy;
2476 if(edge->border) return;
2478 dir= scredge_is_horizontal(edge)?'h':'v';
2480 select_connected_scredge(G.curscreen, edge);
2482 edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
2485 for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
2488 edge_start= MIN2(edge_start, v1->vec.x);
2489 edge_end= MAX2(edge_end, v1->vec.x);
2491 edge_start= MIN2(edge_start, v1->vec.y);
2492 edge_end= MAX2(edge_end, v1->vec.y);
2497 /* nu zijn alle vertices met 'flag==1' degene die verplaatst kunnen worden. */
2498 /* we lopen de areas af en testen vrije ruimte met MINSIZE */
2499 bigger= smaller= 10000;
2500 sa= G.curscreen->areabase.first;
2502 if(dir=='h') { /* als top of down edge select, test hoogte */
2503 if(sa->headertype) {
2509 areaminy= EDGEWIDTH;
2512 if(sa->v1->flag && sa->v4->flag) {
2514 if(sa->v2->vec.y==G.curscreen->sizey-1) /* bovenste edge */
2515 y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
2517 y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
2518 bigger= MIN2(bigger, y1);
2520 else if(sa->v2->flag && sa->v3->flag) {
2522 if(sa->v1->vec.y==0) /* onderste edge */
2523 y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
2525 y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
2526 smaller= MIN2(smaller, y1);
2529 else { /* als left of right edge select, test breedte */
2530 if(sa->v1->flag && sa->v2->flag) {
2531 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
2532 bigger= MIN2(bigger, x1);
2534 else if(sa->v3->flag && sa->v4->flag) {
2535 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
2536 smaller= MIN2(smaller, x1);
2542 mywinset(G.curscreen->mainwin);
2545 getmouseco_sc(mvalo);
2546 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2549 unsigned short event= extern_qread(&val);
2551 if (event==MOUSEY) {
2554 getmouseco_sc(mval);
2556 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2558 delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
2559 delta= CLAMPIS(delta, -smaller, bigger);
2561 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2562 } else if (event==LEFTMOUSE) {
2565 if (ELEM(event, ESCKEY, RIGHTMOUSE))
2567 else if (ELEM(event, SPACEKEY, RETKEY))
2571 draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2574 for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
2576 /* zo is AREAGRID netjes */
2577 if((dir=='v') && v1->vec.x>0 && v1->vec.x<G.curscreen->sizex-1) {
2579 if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
2581 if((dir=='h') && v1->vec.y>0 && v1->vec.y<G.curscreen->sizey-1) {
2584 /* with these lines commented out you can pull the top bar exact to the screen border. */
2585 /* if(delta != bigger && delta != -smaller) { */
2586 v1->vec.y+= AREAGRID-1;
2587 v1->vec.y-= (v1->vec.y % AREAGRID);
2595 removedouble_scrverts();
2596 removedouble_scredges();
2600 glDrawBuffer(GL_BACK);
2601 mainqenter(DRAWEDGES, 1);
2602 dodrawscreen= 1; /* patch! even gets lost,,,? */
2605 static void scrollheader(ScrArea *area)
2607 short mval[2], mvalo[2];
2609 if(area->headbutlen<area->winx) {
2610 area->headbutofs= 0;
2612 else if(area->headbutofs+area->winx > area->headbutlen) {
2613 area->headbutofs= area->headbutlen-area->winx;
2616 getmouseco_sc(mvalo);
2618 while(get_mbut() & M_MOUSE) {
2619 getmouseco_sc(mval);
2620 if(mval[0]!=mvalo[0]) {
2621 area->headbutofs-= (mval[0]-mvalo[0]);
2623 if(area->headbutlen-area->winx < area->headbutofs) area->headbutofs= area->headbutlen-area->winx;
2624 if(area->headbutofs<0) area->headbutofs= 0;
2626 scrarea_do_headchange(area);
2627 scrarea_do_headdraw(area);
2629 screen_swapbuffers();
2633 BIF_wait_for_statechange();
2638 int select_area(int spacetype)
2640 /* vanuit editroutines aanroepen, als er meer area's
2641 * zijn van type 'spacetype' kan er een area aangegeven worden
2643 ScrArea *sa, *sact = NULL;
2645 unsigned short event = 0;
2648 sa= G.curscreen->areabase.first;
2650 if(sa->spacetype==spacetype) {
2658 error("Can't do this! Open correct window");
2663 if(curarea!=sact) areawinset(sact->win);
2667 set_cursor(CURSOR_HELP);
2669 event= extern_qread(&val);
2672 if(event==ESCKEY) break;
2673 if(event==LEFTMOUSE) break;
2674 if(event==SPACEKEY) break;
2676 BIF_wait_for_statechange();
2679 screen_set_cursor(G.curscreen);
2681 /* recalculate winakt */
2682 getmouseco_sc(mval);
2684 if(event==LEFTMOUSE) {
2685 ScrArea *sa= screen_find_area_for_pt(G.curscreen, mval);
2687 if (sa &&sa->spacetype==spacetype) {
2688 G.curscreen->winakt= sa->win;
2689 areawinset(G.curscreen->winakt);
2691 error("wrong window");
2697 if(event==LEFTMOUSE) return 1;
2701 /* ************ END JOIN/SPLIT/MOVE ************** */
2702 /* **************** DRAW SCREENEDGES ***************** */
2704 #define EDGE_EXTEND 3
2706 void drawedge(short x1, short y1, short x2, short y2)
2708 static unsigned int edcol[EDGEWIDTH]= {0x0, 0x505050, 0x909090, 0xF0F0F0, 0x0};
2711 if(x1==x2) { /* vertical */
2715 if (y1==0) y1-= EDGE_EXTEND;
2716 if (y2==G.curscreen->sizey) y2+= EDGE_EXTEND;
2722 for(a=0; a<EDGEWIDTH; a++) {
2723 int rounding= abs(a-EDGEWIDTH2);
2726 glVertex2i(x1-a, y1+rounding);
2727 glVertex2i(x2-a, y2-rounding);
2731 else { /* horizontal */
2735 if (x1==0) x1-= EDGE_EXTEND;
2736 if (x2==G.curscreen->sizex) x2+= EDGE_EXTEND;
2742 for(a=0; a<EDGEWIDTH; a++) {
2743 int rounding= abs(a-EDGEWIDTH2);
2746 glVertex2i(x1+rounding, y1+a);
2747 glVertex2i(x2-rounding, y2+a);
2753 static void drawscredge(ScrEdge *se)
2763 /* borders screen niet tekenen */
2764 /* vanwege resolutie verschillen (PC/SGI files) de linit een
2768 if(v1->x<=1 && v2->x<=1) return;
2769 if(v1->x>=sc->sizex-2 && v2->x>=sc->sizex-2) return;
2770 if(v1->y<=1 && v2->y<=1) return;
2771 if(v1->y>=sc->sizey-2 && v2->y>=sc->sizey-2) return;
2774 drawedge(v1->x, v1->y, v2->x, v2->y);
2777 void drawscreen(void)
2781 mywinset(G.curscreen->mainwin);
2782 myortho2(-0.5, (float)G.curscreen->sizex-0.5, -0.5, (float)G.curscreen->sizey-0.5);
2784 /* two times, because there is no 'win_swap' for this available */
2785 glDrawBuffer(GL_FRONT);
2786 se= G.curscreen->edgebase.first;
2792 glDrawBuffer(GL_BACK);
2793 se= G.curscreen->edgebase.first;
2800 /* ********************************* */
2802 bScreen *default_twosplit()
2804 bScreen *sc= addscreen("screen");
2807 splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
2808 sa= sc->areabase.first;
2809 newspace(sa, SPACE_VIEW3D);
2810 newspace(sa->next, SPACE_INFO);
2815 void initscreen(void)
2822 void screen_draw_info_text(bScreen *sc, char *text) {
2823 Window *oldactwin= winlay_get_active_window();
2827 * Because this is called from within rendering
2828 * internals it is possible our window is not
2831 window_make_active(mainwin);
2833 for (sa= sc->areabase.first; sa; sa= sa->next) {
2834 if (sa->spacetype==SPACE_INFO) {
2835 int x= sa->headbutlen - 28;
2838 areawinset(sa->headwin);
2839 glDrawBuffer(GL_FRONT);
2842 glRecti(x-11, y-6, x+55, y+13);
2845 glRecti(x+55, y-6, x+1280, y+14);
2848 glRasterPos2i(x, y);
2849 BMF_DrawString(G.fonts, text);
2852 glDrawBuffer(GL_BACK);
2854 sa->head_swap= WIN_FRONT_OK;
2858 if (oldactwin && oldactwin!=mainwin) window_make_active(oldactwin);
2861 static int curcursor;
2863 int get_cursor(void) {
2867 void set_cursor(int curs) {
2868 if (!(R.flag & R_RENDERING)) {
2869 if (curs!=curcursor) {
2871 window_set_cursor(mainwin, curs);
2876 void unlink_screen(bScreen *sc) {
2879 for (sa= sc->areabase.first; sa; sa= sa->next)
2883 void warp_pointer(int x, int y)
2885 window_warp_pointer(mainwin, x, y);
2888 void set_timecursor(int nr)
2891 static char number_bitmaps[10][8]= {
2892 {0, 56, 68, 68, 68, 68, 68, 56},
2893 {0, 24, 16, 16, 16, 16, 16, 56},
2894 {0, 60, 66, 32, 16, 8, 4, 126},
2895 {0, 124, 32, 16, 56, 64, 66, 60},
2896 {0, 32, 48, 40, 36, 126, 32, 32},
2897 {0, 124, 4, 60, 64, 64, 68, 56},
2898 {0, 56, 4, 4, 60, 68, 68, 56},
2899 {0, 124, 64, 32, 16, 8, 8, 8},
2900 {0, 60, 66, 66, 60, 66, 66, 60},
2901 {0, 56, 68, 68, 120, 64, 68, 56}
2903 unsigned char mask[16][2];
2904 unsigned char bitmap[16][2];
2907 memset(&bitmap, 0x00, sizeof(bitmap));
2908 memset(&mask, 0xFF, sizeof(mask));
2910 /* print number bottom right justified */
2911 for (idx= 3; nr && idx>=0; idx--) {
2912 char *digit= number_bitmaps[nr%10];
2917 bitmap[i + y*8][x]= digit[i];
2921 curcursor= CURSOR_NONE;
2922 window_set_custom_cursor(mainwin, mask, bitmap);
2923 BIF_renderwin_set_custom_cursor(mask, bitmap);