This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/src/editscreen.c
Ton Roosendaal cd79d25e83 OSX only: the Apple key now is a normal modifier in code, so can be
detected as others, LR_COMMANDKEY

Unline previous commit, Apple key doesnt map to control anymore, but is
handled separate where needed. Now only for undo (Apple-Z)
2004-09-18 13:25:29 +00:00

3125 lines
68 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
* All screen functions that are related to the interface
* handling and drawing. Might be split up as well later...
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#include "BLI_winstuff.h"
#endif
#include "nla.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* isprint */
#include <stdio.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
#include "BMF_Api.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "DNA_action_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_sound_types.h"
#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
#include "BLO_writefile.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_blender.h"
#include "BKE_screen.h"
#include "BIF_editsound.h"
#include "BIF_glutil.h"
#include "BIF_gl.h"
#include "BIF_graphics.h"
#include "BIF_interface.h"
#include "BIF_mainqueue.h"
#include "BIF_mywindow.h"
#include "BIF_renderwin.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toets.h"
#include "BIF_toolbox.h"
#include "BIF_usiblender.h"
#include "BIF_keyval.h"
#include "BIF_resources.h"
#include "BSE_edit.h"
#include "BSE_filesel.h"
#include "BSE_headerbuttons.h"
#include "BSE_view.h"
#include "BPY_extern.h"
#include "mydevice.h"
#include "blendef.h"
#include "render.h"
#include "winlay.h"
/* TIPS:
*
* - WATCH THE EDGES, VERTICES HAVE TO BE IN ORDER...
(lowest pointer first). Otherwise unpredictable effects!
* - problem: flags here are not nicely implemented. After usage
always reset to zero.
*/
static void testareas(void);
static void area_autoplayscreen(void);
static void wait_for_event(void);
/* ********* Globals *********** */
static Window *mainwin= NULL;
static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
static short dodrawscreen= 1;
static ScrArea *areawinar[MAXWIN];
static ScrArea *g_activearea= NULL;
short winqueue_break= 0;
ScrArea *curarea= 0;
/**********************************************************************/
static void screen_set_cursor(bScreen *sc)
{
if (sc->winakt>3) {
ScrArea *sa= areawinar[sc->winakt];
set_cursor(sa->cursor);
} else {
set_cursor(CURSOR_STD);
}
}
void waitcursor(int val)
{
if(val) {
set_cursor(CURSOR_WAIT);
} else {
screen_set_cursor(G.curscreen);
}
}
static int choose_cursor(ScrArea *sa)
{
if (sa->spacetype==SPACE_VIEW3D) {
if(G.obedit) return CURSOR_EDIT;
else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
else return CURSOR_STD;
} else {
return CURSOR_STD;
}
}
void wich_cursor(ScrArea *sa)
{
sa->cursor= choose_cursor(sa);
screen_set_cursor(G.curscreen);
}
void setcursor_space(int spacetype, short cur)
{
bScreen *sc;
ScrArea *sa;
for (sc= G.main->screen.first; sc; sc= sc->id.next)
for (sa= sc->areabase.first; sa; sa= sa->next)
if(sa->spacetype==spacetype)
sa->cursor= cur;
screen_set_cursor(G.curscreen);
}
/* ********* IN/OUT ************* */
void getmouseco_sc(short *mval) /* screen coordinates */
{
getmouse(mval);
}
/* mouse_cursor called during a script (via Window.QHandle) need
* this function for getmouseco_areawin to work: */
void set_g_activearea(ScrArea *sa)
{
if (sa) g_activearea = sa;
}
void getmouseco_areawin(short *mval) /* internal area coordinates */
{
getmouseco_sc(mval);
if(g_activearea && g_activearea->win) {
mval[0]-= g_activearea->winrct.xmin;
mval[1]-= g_activearea->winrct.ymin;
}
}
void getmouseco_headwin(short *mval) /* internal area coordinates */
{
getmouseco_sc(mval);
if(g_activearea && g_activearea->headwin) {
mval[0]-= g_activearea->headrct.xmin;
mval[1]-= g_activearea->headrct.ymin;
}
}
/* *********** STUFF ************** */
static int scredge_is_horizontal(ScrEdge *se)
{
return (se->v1->vec.y == se->v2->vec.y);
}
static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
{
ScrEdge *se;
for (se= sc->edgebase.first; se; se= se->next) {
if (scredge_is_horizontal(se)) {
short min, max;
min= MIN2(se->v1->vec.x, se->v2->vec.x);
max= MAX2(se->v1->vec.x, se->v2->vec.x);
if (abs(mval[1]-se->v1->vec.y)<=2 && mval[0] >= min && mval[0]<=max)
return se;
}
else {
short min, max;
min= MIN2(se->v1->vec.y, se->v2->vec.y);
max= MAX2(se->v1->vec.y, se->v2->vec.y);
if (abs(mval[0]-se->v1->vec.x)<=2 && mval[1] >= min && mval[1]<=max)
return se;
}
}
return NULL;
}
void areawinset(short win)
{
if(win>3) {
curarea= areawinar[win];
if(curarea==0) {
printf("error in areawinar %d ,areawinset\n", win);
return;
}
BIF_SetTheme(curarea);
switch(curarea->spacetype) {
case SPACE_VIEW3D:
G.vd= curarea->spacedata.first;
break;
case SPACE_IPO:
G.sipo= curarea->spacedata.first;
G.v2d= &G.sipo->v2d;
break;
case SPACE_BUTS:
G.buts= curarea->spacedata.first;
G.v2d= &G.buts->v2d;
break;
case SPACE_SEQ: {
SpaceSeq *sseq= curarea->spacedata.first;
G.v2d= &sseq->v2d;
break;
}
case SPACE_OOPS:
G.soops= curarea->spacedata.first;
G.v2d= &G.soops->v2d;
break;
case SPACE_IMAGE:
G.sima= curarea->spacedata.first;
G.v2d= &G.sima->v2d;
break;
case SPACE_SOUND:
G.ssound= curarea->spacedata.first;
G.v2d= &G.ssound->v2d;
break;
case SPACE_ACTION:
G.saction= curarea->spacedata.first;
G.v2d= &G.saction->v2d;
break;
case SPACE_NLA:
G.snla= curarea->spacedata.first;
G.v2d= &G.snla->v2d;
break;
default:
break;
}
}
if(win) mywinset(win);
}
#define SCR_BACK 0.55
#define SCR_ROUND 12
void headerbox(ScrArea *area)
{
float width= area->winx;
glClearColor(SCR_BACK, SCR_BACK, SCR_BACK, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
if(area_is_active_area(area)) BIF_ThemeColor(TH_HEADER);
else BIF_ThemeColor(TH_HEADERDESEL);
/* weird values here... is because of window matrix that centres buttons */
if(area->headertype==HEADERTOP) {
uiSetRoundBox(3);
uiRoundBoxEmboss(-0.5+area->headbutofs, -10.0, width-1.5+area->headbutofs, HEADERY-2.0, SCR_ROUND);
}
else {
uiSetRoundBox(12);
uiRoundBoxEmboss(-0.5+area->headbutofs, -3.5, width-1.5+area->headbutofs, HEADERY+10, SCR_ROUND);
}
uiSetRoundBox(15);
}
int area_is_active_area(ScrArea *area)
{
return (g_activearea && area==g_activearea);
}
void scrarea_do_headdraw(ScrArea *area)
{
if (area->headertype) {
areawinset(area->headwin);
headerbox(area);
/* we make scissor test slightly smaller not to destroy rounded headers */
glScissor(area->headrct.xmin+5, area->headrct.ymin, area->winx-10, HEADERY);
switch(area->spacetype) {
case SPACE_FILE: file_buttons(); break;
case SPACE_INFO: info_buttons(); break;
case SPACE_VIEW3D: view3d_buttons(); break;
case SPACE_IPO: ipo_buttons(); break;
case SPACE_BUTS: buts_buttons(); break;
case SPACE_SEQ: seq_buttons(); break;
case SPACE_IMAGE: image_buttons(); break;
case SPACE_IMASEL: imasel_buttons(); break;
case SPACE_OOPS: oops_buttons(); break;
case SPACE_TEXT: text_buttons(); break;
case SPACE_SCRIPT:script_buttons(); break;
case SPACE_SOUND: sound_buttons(); break;
case SPACE_ACTION: action_buttons(); break;
case SPACE_NLA: nla_buttons(); break;
}
//glScissor(area->winrct.xmin, area->winrct.xmax, area->winx, area->winy);
area->head_swap= WIN_BACK_OK;
}
}
void scrarea_do_headchange(ScrArea *area)
{
float ofs= area->headbutofs;
if (area->headertype==HEADERDOWN) {
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);
} else if (area->headertype==HEADERTOP) {
bwin_ortho2(area->headwin, -0.375+ofs, area->headrct.xmax-area->headrct.xmin-0.375+ofs, -2.375, area->headrct.ymax-area->headrct.ymin-2.375);
}
}
static void openheadwin(ScrArea *sa);
static void closeheadwin(ScrArea *sa);
static void scrarea_change_headertype(ScrArea *sa, int newtype)
{
sa->headertype= newtype;
if (!newtype) {
if (sa->headwin) {
uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
closeheadwin(sa);
}
} else {
if (!sa->headwin) {
openheadwin(sa);
}
}
testareas();
mainqenter(DRAWEDGES, 1);
winqueue_break= 1;
}
static void headmenu(ScrArea *sa)
{
short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
if(val> -1) {
scrarea_change_headertype(sa, val);
}
}
static void addqueue_ext(short win, unsigned short event, short val, char ascii)
{
if (win<4 || !areawinar[win]) {
if(win==0) // other win ids are for mainwin & renderwin
printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
}
else {
BWinEvent evt;
evt.event= event;
evt.val= val;
evt.ascii= ascii;
bwin_qadd(win, &evt);
}
}
void addqueue(short win, unsigned short event, short val)
{
addqueue_ext(win, event, val, 0);
}
void scrarea_queue_winredraw(ScrArea *area)
{
addqueue(area->win, REDRAW, 1);
}
void scrarea_queue_headredraw(ScrArea *area)
{
if (area->headwin) addqueue(area->headwin, REDRAW, 1);
}
void scrarea_queue_redraw(ScrArea *area)
{
scrarea_queue_winredraw(area);
scrarea_queue_headredraw(area);
}
static void scrollheader(ScrArea *area);
static void scrarea_dispatch_header_events(ScrArea *sa)
{
ScrArea *tempsa;
BWinEvent evt;
short do_redraw=0, do_change=0;
areawinset(sa->headwin);
while(bwin_qread(sa->headwin, &evt)) {
if(evt.val) {
if( uiDoBlocks(&curarea->uiblocks, evt.event)!=UI_NOTHING ) evt.event= 0;
switch(evt.event) {
case UI_BUT_EVENT:
do_headerbuttons(evt.val);
break;
case LEFTMOUSE:
if (G.qual & LR_CTRLKEY) {
window_lower(mainwin);
} else {
window_raise(mainwin);
}
break;
case MIDDLEMOUSE:
scrollheader(sa);
break;
case RIGHTMOUSE:
headmenu(sa);
break;
case REDRAW:
do_redraw= 1;
break;
case CHANGED:
sa->head_swap= 0;
do_change= 1;
do_redraw= 1;
break;
default:
if (winqueue_break == 0) {
scrarea_do_winhandle(sa, &evt);
if (winqueue_break == 0) areawinset(sa->headwin);
}
}
if(winqueue_break) return;
}
}
/* test: does window still exist? */
tempsa= areawinar[sa->headwin];
if(tempsa==0) return;
/* this functional separation does not work as well as i expected... */
if(do_change) scrarea_do_headchange(sa);
if(do_redraw) scrarea_do_headdraw(sa);
}
static void scrarea_dispatch_events(ScrArea *sa)
{
ScrArea *tempsa;
BWinEvent evt;
short do_redraw=0, do_change=0;
if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
while(bwin_qread(sa->win, &evt)) {
if(evt.event==REDRAW) {
do_redraw= 1;
}
else if(evt.event==CHANGED) {
sa->win_swap= 0;
do_change= 1;
do_redraw= 1;
}
else {
scrarea_do_winhandle(sa, &evt);
}
if(winqueue_break) return;
}
/* test: does window still exist */
tempsa= areawinar[sa->win];
if(tempsa==0) return;
if (do_change || do_redraw) {
areawinset(sa->win);
if(do_change)
scrarea_do_winchange(curarea);
if(do_redraw)
scrarea_do_windraw(curarea);
}
}
/***/
void markdirty_all()
{
ScrArea *sa;
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
if(sa->win) {
scrarea_queue_winredraw(sa);
sa->win_swap &= ~WIN_FRONT_OK;
}
if(sa->headwin) {
scrarea_queue_headredraw(sa);
sa->head_swap &= ~WIN_FRONT_OK;
}
}
}
int is_allowed_to_change_screen(bScreen *new)
{
/* not when curscreen is full
* not when obedit && old->scene!=new->scene
*/
if(new==0) return 0;
if(G.curscreen->full != SCREENNORMAL) return 0;
if(curarea->full) return 0;
if(G.obedit) {
if(G.curscreen->scene!=new->scene) return 0;
}
return 1;
}
void splash(void *data, int datasize, char *string)
{
ImBuf *bbuf;
int oldwin;
short val;
bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
if (bbuf) {
oldwin = mywinget();
mywinset(G.curscreen->mainwin);
if (string) {
int x, y, maxy;
unsigned int *rect;
rect = bbuf->rect;
maxy = MIN2(bbuf->y, 18);
for (y = 0; y < maxy; y++) {
for (x = 0; x < bbuf->x; x++) {
*rect = 0xffffffff;
rect++;
}
}
}
glDrawBuffer(GL_FRONT);
/*
// this dims the whole screen a bit. I didn't like it afterall
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0,0.0,0.0,0.3);
glRecti(0, 0, G.curscreen->sizex, G.curscreen->sizey);
glDisable(GL_BLEND);
*/
glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);
glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
if (string) {
void *font;
int width;
if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
font= G.fontss;
width= BMF_GetStringWidth(font, string);
glColor3ub(0, 0, 0);
glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
BMF_DrawString(font, string);
}
glFlush();
glDrawBuffer(GL_BACK);
IMB_freeImBuf(bbuf);
// flush input buffers ....
// this might break some things
while (get_mbut()) {
BIF_wait_for_statechange();
}
while(qtest()) {
extern_qread(&val);
}
wait_for_event();
mywinset(oldwin);
markdirty_all();
mainqenter(DRAWEDGES, 1);
}
}
static void moveareas(ScrEdge *edge);
static void joinarea(ScrArea *sa, ScrEdge *onedge);
static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val) {
if (val) {
// don't allow users to edit full screens
if (actarea && actarea->full) {
return;
}
if (evt==LEFTMOUSE) {
moveareas(actedge);
} else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
int edgeop;
if (!actarea->headertype) {
edgeop= pupmenu("Split Area|Join Areas|Add Header");
} else {
edgeop= pupmenu("Split Area|Join Areas|No Header");
}
if (edgeop==1) {
splitarea_interactive(actarea, actedge);
} else if (edgeop==2) {
joinarea(actarea, actedge);
} else if (edgeop==3) {
scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
}
}
}
}
/***/
void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
void test_scale_screen(bScreen *);
static void resize_screens(int x, int y, int w, int h) {
prefstax= x;
prefstay= y;
prefsizx= w;
prefsizy= h;
test_scale_screen(G.curscreen);
testareas();
}
static void init_mainwin(void)
{
int orx, ory, sizex, sizey;
glEnable(GL_SCISSOR_TEST);
window_get_position(mainwin, &orx, &ory);
window_get_size(mainwin, &sizex, &sizey);
/* XXX, temporary stupid fix for minimize at windows */
if (!sizex && !sizey) {
return;
}
mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
resize_screens(orx, ory, sizex, sizey);
}
/***/
static short afterqueue[MAXQUEUE][3];
static int nafterqitems= 0;
void addafterqueue(short win, unsigned short evt, short val)
{
if (nafterqitems<MAXQUEUE) {
afterqueue[nafterqitems][0]= win;
afterqueue[nafterqitems][1]= evt;
afterqueue[nafterqitems][2]= val;
nafterqitems++;
}
}
static void append_afterqueue(void)
{
while (nafterqitems) {
short win= afterqueue[nafterqitems-1][0];
unsigned short evt= afterqueue[nafterqitems-1][1];
short val= afterqueue[nafterqitems-1][2];
addqueue(win, evt, val);
nafterqitems--;
}
}
static char ext_load_str[256]= {0, 0};
void add_readfile_event(char *filename)
{
mainqenter(LOAD_FILE, 1);
strcpy(ext_load_str, filename);
BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
}
static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
static void flush_extqd_events(void) {
if (ext_inputchange) {
mainqenter(INPUTCHANGE, ext_inputchange);
} else if (ext_reshape) {
mainqenter(RESHAPE, ext_redraw);
} else if (ext_redraw) {
mainqenter(REDRAW, ext_redraw);
} else if (ext_mousemove) {
short mouse[2];
getmouseco_sc(mouse);
mainqenter(MOUSEX, mouse[0]);
mainqenter(MOUSEY, mouse[1]);
}
ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
}
unsigned short qtest(void)
{
if (!mainqtest()) {
winlay_process_events(0);
}
return mainqtest();
}
/* return true if events are waiting anywhere */
int anyqtest(void)
{
ScrArea *sa;
if (nafterqitems || qtest()) return 1;
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
if (bwin_qtest(sa->win)) return 1;
if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
}
return 0;
}
static void wait_for_event(void)
{
while (!mainqtest()) {
winlay_process_events(1);
}
}
unsigned short screen_qread(short *val, char *ascii)
{
unsigned short event;
wait_for_event();
event= mainqread(val, ascii);
if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
if(*val) G.qual |= LR_SHIFTKEY;
else G.qual &= ~LR_SHIFTKEY;
}
else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
if(*val) G.qual |= LR_ALTKEY;
else G.qual &= ~LR_ALTKEY;
}
else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
if(*val) G.qual |= LR_CTRLKEY;
else G.qual &= ~LR_CTRLKEY;
}
else if(event==COMMANDKEY) { // OSX
if(*val) G.qual |= LR_COMMANDKEY;
else G.qual &= ~LR_COMMANDKEY;
}
return event;
}
unsigned short extern_qread_ext(short *val, char *ascii)
{
/* stores last INPUTCHANGE and last REDRAW */
unsigned short event;
event= screen_qread(val, ascii);
if(event==RESHAPE) ext_reshape= *val;
else if(event==REDRAW) ext_redraw= *val;
else if(event==INPUTCHANGE) ext_inputchange= *val;
else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
else if((G.qual & (LR_CTRLKEY|LR_ALTKEY)) && event==F3KEY) {
if(*val) BIF_screendump();
}
return event;
}
unsigned short extern_qread(short *val)
{
char ascii;
return extern_qread_ext(val, &ascii);
}
int blender_test_break(void)
{
if (!G.background) {
static double ltime= 0;
double curtime= PIL_check_seconds_timer();
/* only check for breaks every 10 milliseconds
* if we get called more often.
*/
if ((curtime-ltime)>.001) {
ltime= curtime;
while(qtest()) {
short val;
if (extern_qread(&val) == ESCKEY) {
G.afbreek= 1;
}
}
}
}
return (G.afbreek==1);
}
void reset_autosave(void) {
window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
}
static void screen_dispatch_events(void) {
int events_remaining= 1;
ScrArea *sa;
window_make_active(mainwin); // added it here instead of screenmain (ton)
while (events_remaining) {
events_remaining= 0;
winqueue_break= 0;
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
/* first check header, then rest. Header sometimes has initialization code */
if (sa->headwin && bwin_qtest(sa->headwin)) {
scrarea_dispatch_header_events(sa);
events_remaining= 1;
}
if (winqueue_break) break;
if (bwin_qtest(sa->win)) {
scrarea_dispatch_events(sa);
events_remaining= 1;
}
if (winqueue_break) break;
}
if (winqueue_break) break;
}
if (dodrawscreen) {
drawscreen();
dodrawscreen= 0;
}
screen_swapbuffers();
}
static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval)
{
ScrArea *sa;
/* hotspot area of 1 pixel extra */
for (sa= sc->areabase.first; sa; sa= sa->next) {
if( sa->totrct.xmin + 1 < mval[0] )
if( sa->totrct.ymin + 1 < mval[1] )
if( sa->totrct.xmax - 1 > mval[0] )
if( sa->totrct.ymax - 1 > mval[1] )
return sa;
}
return NULL;
}
void screenmain(void)
{
int has_input= 1;
int firsttime = 1;
int onload_script = 0;
window_make_active(mainwin);
while (1) {
unsigned short event;
short val, towin;
char ascii;
flush_extqd_events();
if (nafterqitems && !qtest()) {
append_afterqueue();
event= val= ascii= 0;
} else {
event= screen_qread(&val, &ascii);
}
// window_make_active(mainwin); // (only for inputchange, removed, (ton))
if (event==INPUTCHANGE) {
window_make_active(mainwin);
has_input= val;
}
/* If the main window is active, find the current active ScrArea
* underneath the mouse cursor, updating the headers & cursor for
* the appropriate internal window if things have changed.
*
* If the main window is not active, deactivate the internal
* window.
*/
if (has_input || g_activearea==NULL || G.curscreen->winakt) {
ScrArea *newactarea;
int newactwin;
short mval[2];
getmouseco_sc(mval);
newactarea= screen_find_area_for_pt(G.curscreen, mval);
if (newactarea) {
if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
newactwin= newactarea->headwin;
} else {
newactwin= newactarea->win;
}
} else {
newactwin= 0;
}
if (newactarea && (newactarea != g_activearea)) {
if (g_activearea) scrarea_queue_headredraw(g_activearea);
scrarea_queue_headredraw(newactarea);
set_cursor(newactarea->cursor);
g_activearea= newactarea;
}
/* when you move mouse from header to window, buttons can remain hilited otherwise */
if(newactwin != G.curscreen->winakt) {
if (g_activearea) scrarea_queue_headredraw(g_activearea);
}
G.curscreen->winakt= newactwin;
if (G.curscreen->winakt) {
areawinset(G.curscreen->winakt);
set_cursor(choose_cursor(g_activearea));
}
}
else {
if (g_activearea) {
scrarea_queue_headredraw(g_activearea);
}
g_activearea= NULL;
G.curscreen->winakt= 0;
}
towin= 0;
if (event==WINCLOSE) {
exit_usiblender();
}
else if (event==DRAWEDGES) {
dodrawscreen= 1;
}
else if (event==RESHAPE) {
init_mainwin();
markdirty_all();
dodrawscreen= 1;
}
else if (event==REDRAW) {
markdirty_all();
dodrawscreen= 1;
}
else if (event==AUTOSAVE_FILE) {
BIF_write_autosave();
}
else if (event==LOAD_FILE) {
BIF_read_file(ext_load_str);
sound_initialize_sounds();
}
else if ((event==ONLOAD_SCRIPT) && BPY_has_onload_script()) {
/* event queued in setup_app_data() in blender.c, where G.f is checked */
onload_script = 1;
firsttime = 1; /* see last 'if' in this function */
}
else {
towin= 1;
}
if (!g_activearea) {
towin= 0;
}
else if (!G.curscreen->winakt) {
ScrEdge *actedge;
short mval[2];
getmouseco_sc(mval);
actedge= screen_find_active_scredge(G.curscreen, mval);
if (actedge) {
if (scredge_is_horizontal(actedge)) {
set_cursor(CURSOR_Y_MOVE);
} else {
set_cursor(CURSOR_X_MOVE);
}
screen_edge_edit_event(g_activearea, actedge, event, val);
} else {
set_cursor(CURSOR_STD);
}
towin= 0;
}
else if (event==QKEY) {
if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT||g_activearea->spacetype==SPACE_SCRIPT);
else {
if(val) {
if(okee("Quit Blender?"))
exit_usiblender();
}
towin= 0;
}
}
else if (event==ZKEY) {
if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
switch (which) {
case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
case 6:
if (g_activearea) {
g_activearea->head_swap= 0;
g_activearea->win_swap= 0;
}
break;
}
towin= 0;
}
}
else if (event==SPACEKEY) {
if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT||g_activearea->spacetype==SPACE_SCRIPT);
else {
if(val) toolbox_n();
towin= 0;
}
}
else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
if(val && (G.qual & LR_CTRLKEY)) {
bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
if(is_allowed_to_change_screen(sc)) setscreen(sc);
g_activearea= NULL;
towin= 0;
}
}
else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
if(val && (G.qual & LR_CTRLKEY)) {
area_fullscreen();
g_activearea= NULL;
towin= 0;
}
}
if (towin && event) {
if (blenderqread(event, val))
addqueue_ext(G.curscreen->winakt, event, val, ascii);
}
/* only process subwindow queue's once the
* main queue has been emptyied.
*/
event= qtest();
if (event==0 || event==EXECUTE) {
screen_dispatch_events();
}
/* Bizar hack. The event queue has mutated... */
if ( (firsttime) && (event == 0) ) {
if (onload_script) {
/* OnLoad scriptlink */
BPY_do_pyscript(&G.scene->id, SCRIPT_ONLOAD);
onload_script = 0;
}
else if (G.fileflags & G_FILE_AUTOPLAY) {
// SET AUTOPLAY in G.flags for
// other fileloads
G.flags |= G_FLAGS_AUTOPLAY;
area_autoplayscreen();
// Let The Games Begin
// fake a 'p' keypress
mainqenter(PKEY, 1);
} else {
extern char datatoc_splash_jpg[];
extern int datatoc_splash_jpg_size;
//if (! ((G.main->versionfile >= G.version)
// || G.save_over)) {
splash((void *)datatoc_splash_jpg,
datatoc_splash_jpg_size, NULL);
//}
}
firsttime = 0;
}
}
}
#ifdef _WIN32 // FULLSCREEN
void mainwindow_toggle_fullscreen(int fullscreen){
if (fullscreen) U.uiflag |= USER_FLIPFULLSCREEN;
else U.uiflag &= ~USER_FLIPFULLSCREEN;
window_toggle_fullscreen(mainwin, fullscreen);
}
#endif
void mainwindow_raise(void) {
window_raise(mainwin);
}
void mainwindow_make_active(void) {
window_make_active(mainwin);
}
void mainwindow_close(void) {
window_destroy(mainwin);
mainwin= NULL;
}
void mainwindow_set_filename_to_title(char *filename) {
char str[FILE_MAXDIR + FILE_MAXFILE];
char dir[FILE_MAXDIR];
char file[FILE_MAXFILE];
BLI_split_dirfile(filename, dir, file);
if(BLI_streq(file, ".B.blend") || filename[0] =='\0')
sprintf(str, "Blender");
else
sprintf(str, "Blender [%s]", filename);
window_set_title(mainwin, str);
}
/* ********* AREAS ************* */
void setprefsize(int stax, int stay, int sizx, int sizy)
{
int scrwidth, scrheight;
winlay_get_screensize(&scrwidth, &scrheight);
if(stax<0) stax= 0;
if(stay<0) stay= 0;
if(sizx<320) sizx= 320;
if(sizy<256) sizy= 256;
if(stax+sizx>scrwidth) {
fprintf(stderr," width prob \n");
sizx= scrwidth-stax;
}
if(stay+sizy>scrheight) {
fprintf(stderr," height prob \n");
sizy= scrheight-stay;
}
/* #ifdef __APPLE__ */
/* if(stay+sizy>scrheight-22) sizy= scrheight-22-stay; // 22 = topbar */
/* #endif*/
if(sizx<320 || sizy<256) {
printf("ERROR: illegal prefsize\n");
return;
}
prefstax= stax;
prefstay= stay;
prefsizx= sizx;
prefsizy= sizy;
start_maximized= 0;
}
static ScrVert *screen_addvert(bScreen *sc, short x, short y)
{
ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
sv->vec.x= x;
sv->vec.y= y;
BLI_addtail(&sc->vertbase, sv);
return sv;
}
static void sortscrvert(ScrVert **v1, ScrVert **v2)
{
ScrVert *tmp;
if ((long)*v1 > (long)*v2) {
tmp= *v1;
*v1= *v2;
*v2= tmp;
}
}
static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
{
ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
sortscrvert(&v1, &v2);
se->v1= v1;
se->v2= v2;
BLI_addtail(&sc->edgebase, se);
return se;
}
static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
{
ScrEdge *se;
sortscrvert(&v1, &v2);
for (se= sc->edgebase.first; se; se= se->next)
if(se->v1==v1 && se->v2==v2)
return se;
return NULL;
}
static void removedouble_scrverts(void)
{
ScrVert *v1, *verg;
ScrEdge *se;
ScrArea *sa;
verg= G.curscreen->vertbase.first;
while(verg) {
if(verg->newv==0) { /* !!! */
v1= verg->next;
while(v1) {
if(v1->newv==0) { /* !?! */
if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
/* printf("doublevert\n"); */
v1->newv= verg;
}
}
v1= v1->next;
}
}
verg= verg->next;
}
/* replace pointers in edges and faces */
se= G.curscreen->edgebase.first;
while(se) {
if(se->v1->newv) se->v1= se->v1->newv;
if(se->v2->newv) se->v2= se->v2->newv;
/* edges changed: so.... */
sortscrvert(&(se->v1), &(se->v2));
se= se->next;
}
sa= G.curscreen->areabase.first;
while(sa) {
if(sa->v1->newv) sa->v1= sa->v1->newv;
if(sa->v2->newv) sa->v2= sa->v2->newv;
if(sa->v3->newv) sa->v3= sa->v3->newv;
if(sa->v4->newv) sa->v4= sa->v4->newv;
sa= sa->next;
}
/* remove */
verg= G.curscreen->vertbase.first;
while(verg) {
v1= verg->next;
if(verg->newv) {
BLI_remlink(&G.curscreen->vertbase, verg);
MEM_freeN(verg);
}
verg= v1;
}
}
static void removenotused_scrverts(void)
{
ScrVert *sv, *svn;
ScrEdge *se;
/* we assume edges are ok */
se= G.curscreen->edgebase.first;
while(se) {
se->v1->flag= 1;
se->v2->flag= 1;
se= se->next;
}
sv= G.curscreen->vertbase.first;
while(sv) {
svn= sv->next;
if(sv->flag==0) {
BLI_remlink(&G.curscreen->vertbase, sv);
MEM_freeN(sv);
}
else sv->flag= 0;
sv= svn;
}
}
static void removedouble_scredges(void)
{
ScrEdge *verg, *se, *sn;
/* compare */
verg= G.curscreen->edgebase.first;
while(verg) {
se= verg->next;
while(se) {
sn= se->next;
if(verg->v1==se->v1 && verg->v2==se->v2) {
BLI_remlink(&G.curscreen->edgebase, se);
MEM_freeN(se);
}
se= sn;
}
verg= verg->next;
}
}
static void removenotused_scredges(void)
{
ScrEdge *se, *sen;
ScrArea *sa;
int a=0;
/* sets flags when edge is used in area */
sa= G.curscreen->areabase.first;
while(sa) {
se= screen_findedge(G.curscreen, sa->v1, sa->v2);
if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
else se->flag= 1;
se= screen_findedge(G.curscreen, sa->v2, sa->v3);
if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
else se->flag= 1;
se= screen_findedge(G.curscreen, sa->v3, sa->v4);
if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
else se->flag= 1;
se= screen_findedge(G.curscreen, sa->v4, sa->v1);
if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
else se->flag= 1;
sa= sa->next;
a++;
}
se= G.curscreen->edgebase.first;
while(se) {
sen= se->next;
if(se->flag==0) {
BLI_remlink(&G.curscreen->edgebase, se);
MEM_freeN(se);
}
else se->flag= 0;
se= sen;
}
}
void calc_arearcts(ScrArea *sa)
{
if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+1;
else sa->totrct.xmin= sa->v1->vec.x;
if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-1;
else sa->totrct.xmax= sa->v4->vec.x;
if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+1;
else sa->totrct.ymin= sa->v1->vec.y;
if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-1;
else sa->totrct.ymax= sa->v2->vec.y;
sa->winrct= sa->totrct;
sa->headrct= sa->totrct;
if(sa->headertype) {
if(sa->headertype==HEADERDOWN) {
sa->headrct.ymax= sa->headrct.ymin+HEADERY;
sa->winrct.ymin= sa->headrct.ymax+1;
}
else if(sa->headertype==HEADERTOP) {
sa->headrct.ymin= sa->headrct.ymax-HEADERY;
sa->winrct.ymax= sa->headrct.ymin-1;
}
}
else {
sa->headrct.ymax= sa->headrct.ymin;
}
if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
/* for speedup */
sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
}
static void openheadwin(ScrArea *sa)
{
sa->headwin= myswinopen(G.curscreen->mainwin,
sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
glMatrixMode(GL_MODELVIEW);
areawinar[sa->headwin]= sa; /* oterwise addqueue does not work */
addqueue(sa->headwin, CHANGED, 1);
}
static void openareawin(ScrArea *sa)
{
sa->win= myswinopen(G.curscreen->mainwin,
sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
areawinar[sa->win]= sa; /* otherwise addqueue does not work */
addqueue(sa->win, CHANGED, 1);
}
static void closeheadwin(ScrArea *sa)
{
if(sa->headwin) mywinclose(sa->headwin);
sa->headwin= 0;
}
static void closeareawin(ScrArea *sa)
{
uiFreeBlocksWin(&sa->uiblocks, sa->win);
if(sa->win) mywinclose(sa->win);
sa->win= 0;
}
static void del_area(ScrArea *sa)
{
closeareawin(sa);
closeheadwin(sa);
freespacelist(&sa->spacedata);
uiFreeBlocks(&sa->uiblocks);
uiFreePanels(&sa->panels);
if(sa==curarea) curarea= 0;
if(sa==g_activearea) g_activearea= 0;
}
/* sa2 to sa1 */
static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
{
Panel *pa1, *pa2, *patab;
sa1->headertype= sa2->headertype;
sa1->spacetype= sa2->spacetype;
Mat4CpyMat4(sa1->winmat, sa2->winmat);
freespacelist(&sa1->spacedata);
duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
BLI_freelistN(&sa1->panels);
duplicatelist(&sa1->panels, &sa2->panels);
/* copy pointers */
pa1= sa1->panels.first;
while(pa1) {
patab= sa1->panels.first;
pa2= sa2->panels.first;
while(patab) {
if( pa1->paneltab == pa2) {
pa1->paneltab = patab;
break;
}
patab= patab->next;
pa2= pa2->next;
}
pa1= pa1->next;
}
}
static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
{
ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
sa->cursor= CURSOR_STD;
sa->v1= v1;
sa->v2= v2;
sa->v3= v3;
sa->v4= v4;
sa->headertype= headertype;
sa->spacetype= spacetype;
calc_arearcts(sa);
if (sa->headertype) openheadwin(sa);
openareawin(sa);
BLI_addtail(&sc->areabase, sa);
return sa;
}
static int rcti_eq(rcti *a, rcti *b) {
return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
(a->ymin==b->ymin && a->ymax==b->ymax));
}
static void testareas(void)
{
ScrArea *sa;
/* test for header, if removed, or moved */
/* testen for window, if removed, or moved */
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
rcti oldhr= sa->headrct;
rcti oldwr= sa->winrct;
calc_arearcts(sa);
/* test header */
if (sa->headwin) {
if (!rcti_eq(&oldhr, &sa->headrct)) {
mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
addqueue(sa->headwin, CHANGED, 1);
}
if(sa->headbutlen<sa->winx) {
sa->headbutofs= 0;
addqueue(sa->headwin, CHANGED, 1);
}
else if(sa->headbutofs+sa->winx > sa->headbutlen) {
sa->headbutofs= sa->headbutlen-sa->winx;
addqueue(sa->headwin, CHANGED, 1);
}
}
if (!rcti_eq(&oldwr, &sa->winrct)) {
mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
addqueue(sa->win, CHANGED, 1);
}
}
/* remake global windowarray */
memset(areawinar, 0, sizeof(void *)*MAXWIN);
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
areawinar[sa->headwin]= sa;
areawinar[sa->win]= sa;
}
/* test if winakt is OK */
if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
}
static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
{
/* test if edge is in area, if not,
then find an area that has it */
ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
if(sa) {
se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
}
if(se1!=se && se2!=se && se3!=se && se4!=se) {
sa= G.curscreen->areabase.first;
while(sa) {
/* a bit optimise? */
if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
if(se1==se || se2==se || se3==se || se4==se) return sa;
}
sa= sa->next;
}
}
return sa; /* is null when not find */
}
ScrArea *closest_bigger_area(void)
{
ScrArea *sa, *big=0;
float cent[3], vec[3],len, len1, len2, len3, dist=1000;
short mval[2];
getmouseco_sc(mval);
cent[0]= mval[0];
cent[1]= mval[1];
cent[2]= vec[2]= 0;
sa= G.curscreen->areabase.first;
while(sa) {
if(sa!=curarea) {
if(sa->winy>=curarea->winy) {
/* mimimum of the 4 corners */
vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
len= VecLenf(vec, cent);
vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
len1= VecLenf(vec, cent);
vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
len2= VecLenf(vec, cent);
vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
len3= VecLenf(vec, cent);
len= MIN4(len, len1, len2, len3);
/* plus centre */
vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
len+= 0.5*VecLenf(vec, cent);
/* min size */
len-= sa->winy+sa->winx;
if(len<dist) {
dist= len;
big= sa;
}
}
}
sa= sa->next;
}
if(big) return big;
else return curarea;
}
/* ************ SCREEN MANAGEMENT ************** */
static int statechanged= 0;
void BIF_wait_for_statechange(void)
{
if (!statechanged) {
/* Safety, don't wait more than 0.1 seconds */
double stime= PIL_check_seconds_timer();
while (!statechanged) {
winlay_process_events(1);
if ((PIL_check_seconds_timer()-stime)>0.1) break;
}
statechanged= 0;
}
else PIL_sleep_ms(3); /* statechanged can be set '1' while holding mousebutton, causing locks */
}
void getmouse(short *mval)
{
winlay_process_events(0);
window_get_mouse(mainwin, mval);
}
short get_qual(void)
{
winlay_process_events(0);
return window_get_qual(mainwin);
}
short get_mbut(void)
{
winlay_process_events(0);
return window_get_mbut(mainwin);
}
void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
{
statechanged= 1;
/* accept the extended ascii set (ton) */
if( !val || ascii<32 ) {
ascii= '\0';
}
mainqenter_ext(evt, val, ascii);
}
/* ScrVert ordering in a ScrArea:
2---------3
| |
| |
1---------4
*/
static bScreen *addscreen(char *name) /* use setprefsize() if you want something else than a full windpw */
{
/* this function sets variabele G.curscreen,
* that global is about used everywhere!
*/
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
short startx, starty, endx, endy;
sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
if (!prefsizx) {
prefstax= 0;
prefstay= 0;
winlay_get_screensize(&prefsizx, &prefsizy);
}
startx= prefstax;
starty= prefstay;
endx= prefstax+prefsizx-1;
endy= prefstay+prefsizy-1;
sc->startx= startx; sc->starty= starty;
sc->endx= endx; sc->endy= endy;
sc->sizex= sc->endx-sc->startx+1;
sc->sizey= sc->endy-sc->starty+1;
sc->scene= G.scene;
if (!mainwin) {
#ifdef _WIN32 // FULLSCREEN
if (G.windowstate == G_WINDOWSTATE_FULLSCREEN)
mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, G_WINDOWSTATE_FULLSCREEN);
else
mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
#else
mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
#endif
if (!mainwin) {
printf("ERROR: Unable to open Blender window\n");
exit(1);
}
window_set_handler(mainwin, add_to_mainqueue, NULL);
init_mainwin();
mywinset(1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
myortho2(-0.375, sc->sizex-0.375, -0.375, sc->sizey-0.375);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* for visual speed, but still needed? */
glClearColor(.55, .55, .55, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
window_swap_buffers(mainwin);
warp_pointer(sc->sizex/2, sc->sizey/2);
mainqenter(REDRAW, 1);
}
sc->mainwin= 1;
sv1= screen_addvert(sc, 0, 0);
sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
sv4= screen_addvert(sc, sc->sizex-1, 0);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
screen_addedge(sc, sv3, sv4);
screen_addedge(sc, sv4, sv1);
screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
G.curscreen= sc;
return sc;
}
void setscreen(bScreen *sc)
{
bScreen *sc1;
ScrArea *sa;
short mval[2];
if(sc->full) { /* find associated full */
sc1= G.main->screen.first;
while(sc1) {
sa= sc1->areabase.first;
if(sa->full==sc) {
sc= sc1;
break;
}
sc1= sc1->id.next;
}
if(sc1==0) printf("setscreen error\n");
}
/* de-activate G.curscreen */
if (G.curscreen && G.curscreen != sc) {
sa= G.curscreen->areabase.first;
while(sa) {
if(sa->win) mywinclose(sa->win);
sa->win= 0;
if(sa->headwin) mywinclose(sa->headwin);
sa->headwin= 0;
uiFreeBlocks(&sa->uiblocks);
sa= sa->next;
}
}
else if(G.curscreen) markdirty_all(); /* at least redraw */
if (G.curscreen != sc) {
mywinset(sc->mainwin);
}
G.curscreen= sc;
for (sa= sc->areabase.first; sa; sa= sa->next) {
/* XXX, fixme zr */
/* if (sa->win || sa->headwin) */
/* printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
if (!sa->win)
openareawin(sa);
if (!sa->headwin && sa->headertype)
openheadwin(sa);
}
/* recalculate winakt */
getmouseco_sc(mval);
test_scale_screen(sc);
testareas();
for(sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for(sl= sa->spacedata.first; sl; sl= sl->next) {
sl->area= sa;
if(sl->spacetype==SPACE_OOPS) {
SpaceOops *soops= (SpaceOops *) sl;
/* patch for old files */
if(soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
extern void init_v2d_oops(View2D*);
init_v2d_oops(&soops->v2d);
}
}
else if(sl->spacetype==SPACE_BUTS) {
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->re_align= 1; // force an align call, maybe new panels were added, also for after file reading
}
}
sa->cursor= CURSOR_STD;
}
G.scene= sc->scene;
countall();
G.curscreen->winakt= 0;
curarea= sc->areabase.first;
mainqenter(DRAWEDGES, 1);
dodrawscreen= 1; /* patch! even gets lost,,,? */
winqueue_break= 1; /* means leave queue everywhere */
}
static void splitarea(ScrArea *sa, char dir, float fac);
void area_fullscreen(void) /* with curarea */
{
/* this function toggles: if area is full then the parent will be restored */
bScreen *sc, *oldscreen;
ScrArea *newa, *old;
short headertype, fulltype;
if(curarea->full) {
sc= curarea->full; /* the old screen */
fulltype = sc->full;
// refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
// is set
if (fulltype != SCREENAUTOPLAY || (G.flags & G_FLAGS_AUTOPLAY) == 0) {
sc->full= 0;
/* find old area */
old= sc->areabase.first;
while(old) {
if(old->full) break;
old= old->next;
}
if(old==0) {error("something wrong in areafullscreen"); return;}
if (fulltype == SCREENAUTOPLAY) {
// in autoplay screens the headers are disabled by
// default. So use the old headertype instead
headertype = old->headertype;
} else {
// normal fullscreen. Use current headertype
headertype = curarea->headertype;
}
copy_areadata(old, curarea);
old->headertype = headertype;
old->full= 0;
unlink_screen(G.curscreen);
free_libblock(&G.main->screen, G.curscreen);
G.curscreen= NULL;
setscreen(sc);
}
}
else {
/* is there only 1 area? */
if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
if(curarea->spacetype==SPACE_INFO) return;
G.curscreen->full = SCREENFULL;
old= curarea;
oldscreen= G.curscreen;
sc= addscreen("temp"); /* this sets G.curscreen */
splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
newa= sc->areabase.first;
newspace(newa->next, SPACE_INFO);
curarea= old;
G.curscreen= oldscreen; /* needed because of setscreen */
/* copy area */
copy_areadata(newa, curarea);
curarea->full= oldscreen;
newa->full= oldscreen;
newa->next->full= oldscreen;
setscreen(sc);
wich_cursor(newa);
}
}
static void area_autoplayscreen(void)
{
bScreen *sc, *oldscreen;
ScrArea *newa, *old, *sa;
if (curarea->full) {
area_fullscreen();
}
if (curarea->full == NULL) {
sa = G.curscreen->areabase.first;
while (sa) {
if (sa->spacetype == SPACE_VIEW3D) {
break;
}
sa= sa->next;
}
if (sa) {
areawinset(sa->win);
G.curscreen->full = SCREENAUTOPLAY;
old= curarea;
oldscreen= G.curscreen;
sc= addscreen("temp"); /* this sets G.curscreen */
newa= sc->areabase.first;
curarea= old;
G.curscreen= oldscreen; /* because of setscreen */
/* copy area settings */
copy_areadata(newa, curarea);
newa->headertype= 0;
curarea->full= oldscreen;
newa->full= oldscreen;
setscreen(sc);
wich_cursor(newa);
}
}
}
static void copy_screen(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
ScrArea *sa, *saf;
/* free 'to' */
free_screen(to);
winqueue_break= 1; /* leave queues everywhere */
duplicatelist(&to->vertbase, &from->vertbase);
duplicatelist(&to->edgebase, &from->edgebase);
duplicatelist(&to->areabase, &from->areabase);
s1= from->vertbase.first;
s2= to->vertbase.first;
while(s1) {
s1->newv= s2;
s2= s2->next;
s1= s1->next;
}
se= to->edgebase.first;
while(se) {
se->v1= se->v1->newv;
se->v2= se->v2->newv;
sortscrvert(&(se->v1), &(se->v2));
se= se->next;
}
sa= to->areabase.first;
saf= from->areabase.first;
while(sa) {
sa->v1= sa->v1->newv;
sa->v2= sa->v2->newv;
sa->v3= sa->v3->newv;
sa->v4= sa->v4->newv;
sa->win= 0;
sa->headwin= 0;
sa->spacedata.first= sa->spacedata.last= NULL;
sa->uiblocks.first= sa->uiblocks.last= NULL;
sa->panels.first= sa->panels.last= NULL;
copy_areadata(sa, saf);
sa= sa->next;
saf= saf->next;
}
/* put at zero (needed?) */
s1= from->vertbase.first;
while(s1) {
s1->newv= 0;
s1= s1->next;
}
}
void duplicate_screen(void)
{
bScreen *sc, *oldscreen;
if(G.curscreen->full != SCREENNORMAL) return;
/* make new screen: */
oldscreen= G.curscreen;
sc= addscreen(oldscreen->id.name+2); /* this sets G.curscreen */
copy_screen(sc, oldscreen);
G.curscreen= oldscreen;
setscreen(sc);
}
/* ************ END SCREEN MANAGEMENT ************** */
/* ************ JOIN/SPLIT/MOVE ************** */
static void joinarea(ScrArea *sa, ScrEdge *onedge)
{
ScrArea *sa2;
ScrArea *up=0, *down=0, *right=0, *left=0;
ScrEdge *setest;
short val=0;
sa= test_edge_area(sa, onedge);
if (sa==0) return;
/* which edges? */
/* find directions with same edge */
sa2= G.curscreen->areabase.first;
while(sa2) {
if(sa2 != sa) {
setest= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
if(onedge==setest) right= sa2;
setest= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
if(onedge==setest) down= sa2;
setest= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
if(onedge==setest) left= sa2;
setest= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
if(onedge==setest) up= sa2;
}
sa2= sa2->next;
}
sa2= 0;
setest= 0;
if(left) val++;
if(up) val++;
if(right) val++;
if(down) val++;
if(val==0) return;
else if(val==1) {
if(left) sa2= left;
else if(up) sa2= up;
else if(right) sa2= right;
else if(down) sa2= down;
}
if(sa2) {
/* new area is old sa */
if(sa2==left) {
sa->v1= sa2->v1;
sa->v2= sa2->v2;
screen_addedge(G.curscreen, sa->v2, sa->v3);
screen_addedge(G.curscreen, sa->v1, sa->v4);
}
else if(sa2==up) {
sa->v2= sa2->v2;
sa->v3= sa2->v3;
screen_addedge(G.curscreen, sa->v1, sa->v2);
screen_addedge(G.curscreen, sa->v3, sa->v4);
}
else if(sa2==right) {
sa->v3= sa2->v3;
sa->v4= sa2->v4;
screen_addedge(G.curscreen, sa->v2, sa->v3);
screen_addedge(G.curscreen, sa->v1, sa->v4);
}
else if(sa2==down) {
sa->v1= sa2->v1;
sa->v4= sa2->v4;
screen_addedge(G.curscreen, sa->v1, sa->v2);
screen_addedge(G.curscreen, sa->v3, sa->v4);
}
/* remove edge and area */
/* remlink(&G.curscreen->edgebase, setest); */
/* freeN(setest); */
del_area(sa2);
BLI_remlink(&G.curscreen->areabase, sa2);
MEM_freeN(sa2);
removedouble_scredges();
removenotused_scredges();
removenotused_scrverts(); /* as last */
testareas();
mainqenter(DRAWEDGES, 1);
/* test cursor en inputwindow */
mainqenter(MOUSEY, -1);
}
}
static short testsplitpoint(ScrArea *sa, char dir, float fac)
/* return 0: no split possible */
/* else return (integer) screencoordinate split point */
{
short x, y;
/* area big enough? */
if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
/* to be sure */
if(fac<0.0) fac= 0.0;
if(fac>1.0) fac= 1.0;
if(dir=='h') {
y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY)
y= sa->v2->vec.y- HEADERY;
else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY)
y= sa->v1->vec.y+ HEADERY;
else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
else y-= (y % AREAGRID);
return y;
}
else {
x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
else x-= (x % AREAGRID);
return x;
}
}
static void splitarea(ScrArea *sa, char dir, float fac)
{
bScreen *sc;
ScrArea *newa=NULL;
ScrVert *sv1, *sv2;
short split;
if(sa==0) return;
split= testsplitpoint(sa, dir, fac);
if(split==0) return;
sc= G.curscreen;
areawinset(sa->win);
if(dir=='h') {
/* new vertices */
sv1= screen_addvert(sc, sa->v1->vec.x, split);
sv2= screen_addvert(sc, sa->v4->vec.x, split);
/* new edges */
screen_addedge(sc, sa->v1, sv1);
screen_addedge(sc, sv1, sa->v2);
screen_addedge(sc, sa->v3, sv2);
screen_addedge(sc, sv2, sa->v4);
screen_addedge(sc, sv1, sv2);
/* new areas: top */
newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
copy_areadata(newa, sa);
/* area below */
sa->v2= sv1;
sa->v3= sv2;
}
else {
/* new vertices */
sv1= screen_addvert(sc, split, sa->v1->vec.y);
sv2= screen_addvert(sc, split, sa->v2->vec.y);
/* new edges */
screen_addedge(sc, sa->v1, sv1);
screen_addedge(sc, sv1, sa->v4);
screen_addedge(sc, sa->v2, sv2);
screen_addedge(sc, sv2, sa->v3);
screen_addedge(sc, sv1, sv2);
/* new areas: left */
newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
copy_areadata(newa, sa);
/* area right */
sa->v1= sv1;
sa->v2= sv2;
}
if(sa->spacetype==SPACE_BUTS) {
addqueue(sa->win, UI_BUT_EVENT, B_BUTSHOME);
addqueue(newa->win, UI_BUT_EVENT, B_BUTSHOME);
}
/* remove double vertices en edges */
removedouble_scrverts();
removedouble_scredges();
removenotused_scredges();
mainqenter(DRAWEDGES, 1);
dodrawscreen= 1; /* patch! event gets lost,,,? */
testareas();
}
static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
{
int split= testsplitpoint(sa, dir, fac);
if (split) {
if(dir=='h') {
sdrawXORline(sa->totrct.xmin, split, sa->totrct.xmax, split);
sdrawXORline(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
} else {
sdrawXORline(split, sa->totrct.ymin, split, sa->totrct.ymax);
sdrawXORline(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
}
}
}
static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
{
ScrArea *sa= area;
float fac= 0.0;
unsigned short event;
short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
char dir;
if(sa->win==0) return;
if(sa->full) return;
dir= scredge_is_horizontal(onedge)?'v':'h';
mywinset(G.curscreen->mainwin);
/* should already have a good matrix */
glReadBuffer(GL_FRONT);
glDrawBuffer(GL_FRONT);
/* keep track of grid and minsize */
while(ok==0) {
getmouseco_sc(mval);
if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
if (!first) {
scrarea_draw_splitpoint(sa, dir, fac);
}
if(dir=='h') {
fac= mval[1]- (sa->v1->vec.y);
fac/= sa->v2->vec.y- sa->v1->vec.y;
} else {
fac= mval[0]- sa->v1->vec.x;
fac/= sa->v4->vec.x- sa->v1->vec.x;
}
split= testsplitpoint(sa, dir, fac);
if (split) {
scrarea_draw_splitpoint(sa, dir, fac);
} else {
ok= -1;
}
mvalo[0]= mval[0];
mvalo[1]= mval[1];
first= 0;
}
event= extern_qread(&val);
if(val && event==LEFTMOUSE) {
if(dir=='h') {
fac= split- (sa->v1->vec.y);
fac/= sa->v2->vec.y- sa->v1->vec.y;
}
else {
fac= split- sa->v1->vec.x;
fac/= sa->v4->vec.x- sa->v1->vec.x;
}
ok= 1;
}
if(val && (event==ESCKEY || event==RIGHTMOUSE)) {
ok= -1;
}
glFlush();
}
if (!first) {
scrarea_draw_splitpoint(sa, dir, fac);
glFlush();
}
glReadBuffer(GL_BACK);
glDrawBuffer(GL_BACK);
if(ok==1) {
splitarea(sa, dir, fac);
mainqenter(DRAWEDGES, 1);
dodrawscreen= 1; /* patch! event gets lost,,,? */
}
}
View3D *find_biggest_view3d(void)
{
ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
if (sa) {
return (View3D*) sa->spacedata.first;
} else {
return NULL;
}
}
ScrArea *find_biggest_area_of_type(int spacecode)
{
ScrArea *sa, *biggest= NULL;
int bigsize= 0;
for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
if (spacecode==0 || sa->spacetype==spacecode) {
int x= sa->v3->vec.x - sa->v1->vec.x;
int y= sa->v3->vec.y - sa->v1->vec.y;
int size= x*x + y*y;
if (!biggest || size>bigsize) {
biggest= sa;
bigsize= size;
}
}
}
return biggest;
}
ScrArea *find_biggest_area(void)
{
return find_biggest_area_of_type(0);
}
static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
{
ScrEdge *se;
ScrVert *sv;
int oneselected;
char dir;
/* select connected, only in the right direction */
/* 'dir' is the direction of EDGE */
if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
else dir= 'h';
sv= sc->vertbase.first;
while(sv) {
sv->flag= 0;
sv= sv->next;
}
edge->v1->flag= 1;
edge->v2->flag= 1;
oneselected= 1;
while(oneselected) {
se= sc->edgebase.first;
oneselected= 0;
while(se) {
if(se->v1->flag + se->v2->flag==1) {
if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
se->v1->flag= se->v2->flag= 1;
oneselected= 1;
}
if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
se->v1->flag= se->v2->flag= 1;
oneselected= 1;
}
}
se= se->next;
}
}
}
void test_scale_screen(bScreen *sc)
/* test if screen vertices should be scaled */
/* also check offset */
{
ScrVert *sv=0;
ScrEdge *se;
ScrArea *sa, *san;
int yval;
float facx, facy, tempf, min[2], max[2];
sc->startx= prefstax;
sc->starty= prefstay;
sc->endx= prefstax+prefsizx-1;
sc->endy= prefstay+prefsizy-1;
/* calculate size */
sv= sc->vertbase.first;
min[0]= min[1]= 0.0;
max[0]= sc->sizex;
max[1]= sc->sizey;
while(sv) {
min[0]= MIN2(min[0], sv->vec.x);
min[1]= MIN2(min[1], sv->vec.y);
max[0]= MAX2(max[0], sv->vec.x);
max[1]= MAX2(max[1], sv->vec.y);
sv= sv->next;
}
/* always make 0.0 left under */
sv= sc->vertbase.first;
while(sv) {
sv->vec.x -= min[0];
sv->vec.y -= min[1];
sv= sv->next;
}
sc->sizex= max[0]-min[0];
sc->sizey= max[1]-min[1];
if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
facx= prefsizx;
facx/= (float)sc->sizex;
facy= prefsizy;
facy/= (float)sc->sizey;
/* make sure it fits! */
sv= sc->vertbase.first;
while(sv) {
tempf= ((float)sv->vec.x)*facx;
sv->vec.x= (short)(tempf+0.5);
sv->vec.x+= AREAGRID-1;
sv->vec.x-= (sv->vec.x % AREAGRID);
CLAMP(sv->vec.x, 0, prefsizx);
tempf= ((float)sv->vec.y )*facy;
sv->vec.y= (short)(tempf+0.5);
sv->vec.y+= AREAGRID-1;
sv->vec.y-= (sv->vec.y % AREAGRID);
CLAMP(sv->vec.y, 0, prefsizy);
sv= sv->next;
}
sc->sizex= prefsizx;
sc->sizey= prefsizy;
}
/* test for collapsed areas. This could happen in some blender version... */
sa= sc->areabase.first;
while(sa) {
san= sa->next;
if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
del_area(sa);
BLI_remlink(&sc->areabase, sa);
MEM_freeN(sa);
}
sa= san;
}
/* make each window at least HEADERY high */
sa= sc->areabase.first;
while(sa) {
if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
/* lower edge */
se= screen_findedge(sc, sa->v4, sa->v1);
if(se && sa->v1!=sa->v2 ) {
select_connected_scredge(sc, se);
/* all selected vertices get the right offset */
yval= sa->v2->vec.y-HEADERY;
sv= sc->vertbase.first;
while(sv) {
/* if is a collapsed area */
if(sv!=sa->v2 && sv!=sa->v3) {
if(sv->flag) sv->vec.y= yval;
}
sv= sv->next;
}
}
}
sa= sa->next;
}
}
static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
{
if (dir=='h') {
sdrawXORline(start, dist, end, dist);
sdrawXORline(start, dist+1, end, dist+1);
} else {
sdrawXORline(dist, start, dist, end);
sdrawXORline(dist+1, start, dist+1, end);
}
}
static void moveareas(ScrEdge *edge)
{
ScrVert *v1;
ScrArea *sa;
short mvalo[2];
short edge_start, edge_end, edge_position;
short bigger, smaller, headery, areaminy;
int delta, doit;
char dir;
if(edge->border) return;
dir= scredge_is_horizontal(edge)?'h':'v';
select_connected_scredge(G.curscreen, edge);
edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
edge_start= 10000;
edge_end= -10000;
for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
if (v1->flag) {
if (dir=='h') {
edge_start= MIN2(edge_start, v1->vec.x);
edge_end= MAX2(edge_end, v1->vec.x);
} else {
edge_start= MIN2(edge_start, v1->vec.y);
edge_end= MAX2(edge_end, v1->vec.y);
}
}
}
/* now all verices with 'flag==1' are the ones that can be moved. */
/* we check all areas and test for free space with MINSIZE */
bigger= smaller= 10000;
sa= G.curscreen->areabase.first;
while(sa) {
if(dir=='h') { /* if top or down edge selected, test height */
if(sa->headertype) {
headery= HEADERY;
areaminy= AREAMINY;
}
else {
headery= 0;
areaminy= AREAMINY; /*areaminy= EDGEWIDTH;*/
}
if(sa->v1->flag && sa->v4->flag) {
int y1;
if(sa->v2->vec.y==G.curscreen->sizey-1) /* top edge */
y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
else
y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
bigger= MIN2(bigger, y1);
}
else if(sa->v2->flag && sa->v3->flag) {
int y1;
if(sa->v1->vec.y==0) /* bottom edge */
y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
else
y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
smaller= MIN2(smaller, y1);
}
}
else { /* if left or right edge selected, test width */
if(sa->v1->flag && sa->v2->flag) {
int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
bigger= MIN2(bigger, x1);
}
else if(sa->v3->flag && sa->v4->flag) {
int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
smaller= MIN2(smaller, x1);
}
}
sa= sa->next;
}
mywinset(G.curscreen->mainwin);
glReadBuffer(GL_FRONT);
glDrawBuffer(GL_FRONT);
doit= delta= 0;
getmouseco_sc(mvalo);
draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
while (!doit) {
short val;
unsigned short event= extern_qread(&val);
if (event==MOUSEY) {
short mval[2];
getmouseco_sc(mval);
draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
delta= CLAMPIS(delta, -smaller, bigger);
draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
glFlush();
}
else if (event==LEFTMOUSE) {
doit= 1;
}
else if (val) {
if (ELEM(event, ESCKEY, RIGHTMOUSE))
doit= -1;
else if (ELEM(event, SPACEKEY, RETKEY))
doit= 1;
}
}
draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
glFlush();
glReadBuffer(GL_BACK);
glDrawBuffer(GL_BACK);
if (doit==1) {
for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
if (v1->flag) {
/* that way a nice AREAGRID */
if((dir=='v') && v1->vec.x>0 && v1->vec.x<G.curscreen->sizex-1) {
v1->vec.x+= delta;
if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
}
if((dir=='h') && v1->vec.y>0 && v1->vec.y<G.curscreen->sizey-1) {
v1->vec.y+= delta;
/* with these lines commented out you can pull the top bar exact to the screen border. */
/* if(delta != bigger && delta != -smaller) { */
v1->vec.y+= AREAGRID-1;
v1->vec.y-= (v1->vec.y % AREAGRID);
/* } */
}
}
v1->flag= 0;
}
removedouble_scrverts();
removedouble_scredges();
testareas();
}
mainqenter(DRAWEDGES, 1);
dodrawscreen= 1; /* patch! event gets lost,,,? */
}
static void scrollheader(ScrArea *area)
{
short mval[2], mvalo[2];
if(area->headbutlen<area->winx) {
area->headbutofs= 0;
}
else if(area->headbutofs+area->winx > area->headbutlen) {
area->headbutofs= area->headbutlen-area->winx;
}
getmouseco_sc(mvalo);
while(get_mbut() & M_MOUSE) {
getmouseco_sc(mval);
if(mval[0]!=mvalo[0]) {
area->headbutofs-= (mval[0]-mvalo[0]);
if(area->headbutlen-area->winx < area->headbutofs) area->headbutofs= area->headbutlen-area->winx;
if(area->headbutofs<0) area->headbutofs= 0;
scrarea_do_headchange(area);
scrarea_do_headdraw(area);
screen_swapbuffers();
mvalo[0]= mval[0];
} else {
BIF_wait_for_statechange();
}
}
}
int select_area(int spacetype)
{
/* call from edit routines, when there are more areas
* of type 'spacetype', you can indicate an area manually
*/
ScrArea *sa, *sact = NULL;
int tot=0;
unsigned short event = 0;
short val, mval[2];
sa= G.curscreen->areabase.first;
while(sa) {
if(sa->spacetype==spacetype) {
sact= sa;
tot++;
}
sa= sa->next;
}
if(tot==0) {
error("Can't do this! Open correct window");
return 0;
}
if(tot==1) {
if(curarea!=sact) areawinset(sact->win);
return 1;
}
else if(tot>1) {
set_cursor(CURSOR_HELP);
while(1) {
event= extern_qread(&val);
if (val) {
if(event==ESCKEY) break;
if(event==LEFTMOUSE) break;
if(event==SPACEKEY) break;
} else {
BIF_wait_for_statechange();
}
}
screen_set_cursor(G.curscreen);
/* recalculate winakt */
getmouseco_sc(mval);
if(event==LEFTMOUSE) {
ScrArea *sa= screen_find_area_for_pt(G.curscreen, mval);
if (sa &&sa->spacetype==spacetype) {
G.curscreen->winakt= sa->win;
areawinset(G.curscreen->winakt);
} else {
error("Wrong window");
return 0;
}
}
}
if(event==LEFTMOUSE) return 1;
else return 0;
}
/* ************ END JOIN/SPLIT/MOVE ************** */
/* **************** DRAW SCREENEDGES ***************** */
void draw_area_emboss(ScrArea *sa)
{
/* set transp line */
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
/* right */
glColor4ub(0,0,0, 80);
sdrawline(sa->winx-1, 0, sa->winx-1, sa->winy-1);
/* bottom */
if(sa->headertype!=HEADERDOWN) {
glColor4ub(0,0,0, 128);
sdrawline(0, 0, sa->winx-1, 0);
}
/* top */
if(sa->headertype!=HEADERTOP) {
glColor4ub(255,255,255, 96);
sdrawline(0, sa->winy-1, sa->winx-1, sa->winy-1);
}
/* left */
glColor4ub(255,255,255, 80);
sdrawline(0, 0, 0, sa->winy);
glDisable( GL_BLEND );
/* for test */
if(FALSE && sa->spacetype==SPACE_VIEW3D) {
cpack(0xA0A0A0);
uiSetRoundBox(31);
uiRoundBoxEmboss(5.0, 5.0, 25.0, 100.0, 8.0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glRasterPos2f(8.0, 10.0);
BIF_draw_icon(ICON_MATERIAL_HLT);
glRasterPos2f(8.0, 30.0);
BIF_draw_icon(ICON_IPO_HLT);
glRasterPos2f(8.0, 50.0);
BIF_draw_icon(ICON_HOME);
glRasterPos2f(8.0, 70.0);
BIF_draw_icon(ICON_BORDERMOVE);
glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_BLEND);
}
}
void drawscredge_area(ScrArea *sa)
{
short x1= sa->v1->vec.x;
short y1= sa->v1->vec.y;
short x2= sa->v3->vec.x;
short y2= sa->v3->vec.y;
/* this to fill the (undrawn) edge area with back color first */
glColor3f(SCR_BACK,SCR_BACK,SCR_BACK);
sdrawline(x2, y1, x2, y2);
sdrawline(x1, y1, x2, y1);
cpack(0x0);
/* right border area */
if(sa->headertype==HEADERTOP) sdrawline(x2, y1, x2, y2-SCR_ROUND);
else if(sa->headertype==HEADERDOWN) sdrawline(x2, y1+SCR_ROUND, x2, y2);
else sdrawline(x2, y1, x2, y2);
/* left border area */
if(sa->headertype==HEADERTOP) sdrawline(x1, y1, x1, y2-SCR_ROUND);
else if(sa->headertype==HEADERDOWN) sdrawline(x1, y1+SCR_ROUND, x1, y2);
else sdrawline(x1, y1, x1, y2);
/* top border area */
if(sa->headertype==HEADERTOP) sdrawline(x1+SCR_ROUND, y2, x2-SCR_ROUND, y2);
else sdrawline(x1, y2, x2, y2);
/* bottom border area */
if(sa->headertype==HEADERDOWN) sdrawline(x1+SCR_ROUND, y1, x2-SCR_ROUND, y1);
else sdrawline(x1, y1, x2, y1);
}
void drawscreen(void)
{
ScrArea *sa;
mywinset(G.curscreen->mainwin);
myortho2(-0.375, (float)G.curscreen->sizex-0.375, -0.375, (float)G.curscreen->sizey-0.375);
sa= G.curscreen->areabase.first;
while(sa) {
drawscredge_area(sa);
sa= sa->next;
}
/* this double draw patch seems to be needed for certain sgi's (octane, indigo2) */
glDrawBuffer(GL_FRONT);
sa= G.curscreen->areabase.first;
while(sa) {
drawscredge_area(sa);
sa= sa->next;
}
glDrawBuffer(GL_BACK);
}
/* ********************************* */
bScreen *default_twosplit()
{
bScreen *sc= addscreen("screen");
ScrArea *sa;
splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
sa= sc->areabase.first;
newspace(sa, SPACE_VIEW3D);
newspace(sa->next, SPACE_INFO);
return sc;
}
void initscreen(void)
{
default_twosplit();
}
/***/
void screen_draw_info_text(bScreen *sc, char *text) {
Window *oldactwin= winlay_get_active_window();
ScrArea *sa;
/*
* Because this is called from within rendering
* internals it is possible our window is not
* active.
*/
window_make_active(mainwin);
for (sa= sc->areabase.first; sa; sa= sa->next) {
if (sa->spacetype==SPACE_INFO) {
int x= sa->headbutlen - 28;
int y= 6;
areawinset(sa->headwin);
glDrawBuffer(GL_FRONT);
cpack(0xA08060);
glRecti(x-11, y-6, x+55, y+13);
cpack(0x909090);
glRecti(x+55, y-6, x+1280, y+14);
cpack(0x0);
glRasterPos2i(x, y);
BMF_DrawString(G.fonts, text);
glFlush();
glDrawBuffer(GL_BACK);
sa->head_swap= WIN_FRONT_OK;
}
}
if (oldactwin && oldactwin!=mainwin) window_make_active(oldactwin);
}
static int curcursor;
int get_cursor(void) {
return curcursor;
}
void set_cursor(int curs) {
if (!(R.flag & R_RENDERING) && G.background == 0) {
if (curs!=curcursor) {
curcursor= curs;
window_set_cursor(mainwin, curs);
}
}
}
void unlink_screen(bScreen *sc) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next)
del_area(sa);
}
void warp_pointer(int x, int y)
{
window_warp_pointer(mainwin, x, y);
}
void set_timecursor(int nr)
{
/* 10 8x8 digits */
static char number_bitmaps[10][8]= {
{0, 56, 68, 68, 68, 68, 68, 56},
{0, 24, 16, 16, 16, 16, 16, 56},
{0, 60, 66, 32, 16, 8, 4, 126},
{0, 124, 32, 16, 56, 64, 66, 60},
{0, 32, 48, 40, 36, 126, 32, 32},
{0, 124, 4, 60, 64, 64, 68, 56},
{0, 56, 4, 4, 60, 68, 68, 56},
{0, 124, 64, 32, 16, 8, 8, 8},
{0, 60, 66, 66, 60, 66, 66, 60},
{0, 56, 68, 68, 120, 64, 68, 56}
};
unsigned char mask[16][2];
unsigned char bitmap[16][2];
int i, idx;
memset(&bitmap, 0x00, sizeof(bitmap));
memset(&mask, 0xFF, sizeof(mask));
/* print number bottom right justified */
for (idx= 3; nr && idx>=0; idx--) {
char *digit= number_bitmaps[nr%10];
int x = idx%2;
int y = idx/2;
for (i=0; i<8; i++)
bitmap[i + y*8][x]= digit[i];
nr/= 10;
}
curcursor= CURSOR_NONE;
window_set_custom_cursor(mainwin, mask, bitmap, 7, 7);
BIF_renderwin_set_custom_cursor(mask, bitmap);
}