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/editors/screen/screen_edit.c
Ton Roosendaal 3a58eddec5 2.5
The basics for InfoSpace.
Also added InfoSpace data to area by default, older files allowed to
have nothing here (space empty). (prevents reported crasher in switching
space info to others).

Also: added ifdeffed code in readfile.c to debug missing memory frees
from data read from files. (instead of "data from SCR" it will print
the actual struct names).
2008-12-14 10:52:48 +00:00

1081 lines
24 KiB
C

/**
* $Id:
*
* ***** BEGIN GPL 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.
*
* 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) 2008 Blender Foundation.
* All rights reserved.
*
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_vec_types.h"
#include "BLI_blenlib.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "wm_subwindow.h"
#include "screen_intern.h" /* own module include */
/* ******************* screen vert, edge, area managing *********************** */
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 (*v1 > *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;
}
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;
}
void removedouble_scrverts(bScreen *sc)
{
ScrVert *v1, *verg;
ScrEdge *se;
ScrArea *sa;
verg= sc->vertbase.first;
while(verg) {
if(verg->newv==NULL) { /* !!! */
v1= verg->next;
while(v1) {
if(v1->newv==NULL) { /* !?! */
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= sc->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= sc->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= sc->vertbase.first;
while(verg) {
v1= verg->next;
if(verg->newv) {
BLI_remlink(&sc->vertbase, verg);
MEM_freeN(verg);
}
verg= v1;
}
}
void removenotused_scrverts(bScreen *sc)
{
ScrVert *sv, *svn;
ScrEdge *se;
/* we assume edges are ok */
se= sc->edgebase.first;
while(se) {
se->v1->flag= 1;
se->v2->flag= 1;
se= se->next;
}
sv= sc->vertbase.first;
while(sv) {
svn= sv->next;
if(sv->flag==0) {
BLI_remlink(&sc->vertbase, sv);
MEM_freeN(sv);
}
else sv->flag= 0;
sv= svn;
}
}
void removedouble_scredges(bScreen *sc)
{
ScrEdge *verg, *se, *sn;
/* compare */
verg= sc->edgebase.first;
while(verg) {
se= verg->next;
while(se) {
sn= se->next;
if(verg->v1==se->v1 && verg->v2==se->v2) {
BLI_remlink(&sc->edgebase, se);
MEM_freeN(se);
}
se= sn;
}
verg= verg->next;
}
}
void removenotused_scredges(bScreen *sc)
{
ScrEdge *se, *sen;
ScrArea *sa;
int a=0;
/* sets flags when edge is used in area */
sa= sc->areabase.first;
while(sa) {
se= screen_findedge(sc, sa->v1, sa->v2);
if(se==0) printf("error: area %d edge 1 doesn't exist\n", a);
else se->flag= 1;
se= screen_findedge(sc, sa->v2, sa->v3);
if(se==0) printf("error: area %d edge 2 doesn't exist\n", a);
else se->flag= 1;
se= screen_findedge(sc, sa->v3, sa->v4);
if(se==0) printf("error: area %d edge 3 doesn't exist\n", a);
else se->flag= 1;
se= screen_findedge(sc, sa->v4, sa->v1);
if(se==0) printf("error: area %d edge 4 doesn't exist\n", a);
else se->flag= 1;
sa= sa->next;
a++;
}
se= sc->edgebase.first;
while(se) {
sen= se->next;
if(se->flag==0) {
BLI_remlink(&sc->edgebase, se);
MEM_freeN(se);
}
else se->flag= 0;
se= sen;
}
}
/* adds no space data */
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->v1= v1;
sa->v2= v2;
sa->v3= v3;
sa->v4= v4;
sa->headertype= headertype;
sa->spacetype= sa->butspacetype= spacetype;
BLI_addtail(&sc->areabase, sa);
return sa;
}
static void screen_delarea(bScreen *sc, ScrArea *sa)
{
/* XXX need context to cancel operators ED_area_exit(C, sa); */
BKE_screen_area_free(sa);
BLI_remlink(&sc->areabase, sa);
MEM_freeN(sa);
}
/* return 0: no split possible */
/* else return (integer) screencoordinate split point */
static short testsplitpoint(wmWindow *win, ScrArea *sa, char dir, float fac)
{
short x, y;
// area big enough?
if(dir=='v' && (sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX)) return 0;
if(dir=='h' && (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(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;
}
}
ScrArea *area_split(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac)
{
ScrArea *newa=NULL;
ScrVert *sv1, *sv2;
short split;
if(sa==NULL) return NULL;
split= testsplitpoint(win, sa, dir, fac);
if(split==0) return NULL;
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);
area_copy_data(newa, sa, 0);
/* 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);
area_copy_data(newa, sa, 0);
/* area right */
sa->v1= sv1;
sa->v2= sv2;
}
/* remove double vertices en edges */
removedouble_scrverts(sc);
removedouble_scredges(sc);
removenotused_scredges(sc);
return newa;
}
/* empty screen, with 1 dummy area without spacedata */
/* uses window size */
bScreen *screen_add(wmWindow *win, char *name)
{
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
sc= alloc_libblock(&G.main->screen, ID_SCR, name);
sc->scene= G.scene;
sc->do_refresh= 1;
win->screen= sc;
sv1= screen_addvert(sc, 0, 0);
sv2= screen_addvert(sc, 0, win->sizey-1);
sv3= screen_addvert(sc, win->sizex-1, win->sizey-1);
sv4= screen_addvert(sc, win->sizex-1, 0);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
screen_addedge(sc, sv3, sv4);
screen_addedge(sc, sv4, sv1);
/* dummy type, no spacedata */
screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
return sc;
}
static void screen_copy(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
ScrArea *sa, *saf;
/* free contents of 'to', is from blenkernel screen.c */
free_screen(to);
BLI_duplicatelist(&to->vertbase, &from->vertbase);
BLI_duplicatelist(&to->edgebase, &from->edgebase);
BLI_duplicatelist(&to->areabase, &from->areabase);
to->regionbase.first= to->regionbase.last= NULL;
s2= to->vertbase.first;
for(s1= from->vertbase.first; s1; s1= s1->next, s2= s2->next) {
s1->newv= s2;
}
for(se= to->edgebase.first; se; se= se->next) {
se->v1= se->v1->newv;
se->v2= se->v2->newv;
sortscrvert(&(se->v1), &(se->v2));
}
saf= from->areabase.first;
for(sa= to->areabase.first; sa; sa= sa->next, saf= saf->next) {
sa->v1= sa->v1->newv;
sa->v2= sa->v2->newv;
sa->v3= sa->v3->newv;
sa->v4= sa->v4->newv;
sa->spacedata.first= sa->spacedata.last= NULL;
sa->uiblocks.first= sa->uiblocks.last= NULL;
sa->panels.first= sa->panels.last= NULL;
sa->regionbase.first= sa->regionbase.last= NULL;
sa->actionzones.first= sa->actionzones.last= NULL;
sa->scriptlink.totscript= 0;
area_copy_data(sa, saf, 0);
}
/* put at zero (needed?) */
for(s1= from->vertbase.first; s1; s1= s1->next)
s1->newv= NULL;
}
/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
/* -1 = not valid check */
/* used with join operator */
int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb)
{
ScrVert *sav1, *sav2, *sav3, *sav4;
ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
if(sa==NULL || sb==NULL) return -1;
sav1= sa->v1;
sav2= sa->v2;
sav3= sa->v3;
sav4= sa->v4;
sbv1= sb->v1;
sbv2= sb->v2;
sbv3= sb->v3;
sbv4= sb->v4;
if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
return 0;
}
else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
return 1;
}
else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
return 2;
}
else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
return 3;
}
return -1;
}
/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
* used by the split, join operators
*/
int screen_area_join(bScreen* scr, ScrArea *sa1, ScrArea *sa2)
{
int dir;
dir = area_getorientation(scr, sa1, sa2);
/*printf("dir is : %i \n", dir);*/
if (dir < 0)
{
if (sa1 ) sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
if (sa2 ) sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
return 0;
}
if(dir == 0) {
sa1->v1= sa2->v1;
sa1->v2= sa2->v2;
screen_addedge(scr, sa1->v2, sa1->v3);
screen_addedge(scr, sa1->v1, sa1->v4);
}
else if(dir == 1) {
sa1->v2= sa2->v2;
sa1->v3= sa2->v3;
screen_addedge(scr, sa1->v1, sa1->v2);
screen_addedge(scr, sa1->v3, sa1->v4);
}
else if(dir == 2) {
sa1->v3= sa2->v3;
sa1->v4= sa2->v4;
screen_addedge(scr, sa1->v2, sa1->v3);
screen_addedge(scr, sa1->v1, sa1->v4);
}
else if(dir == 3) {
sa1->v1= sa2->v1;
sa1->v4= sa2->v4;
screen_addedge(scr, sa1->v1, sa1->v2);
screen_addedge(scr, sa1->v3, sa1->v4);
}
screen_delarea(scr, sa2);
removedouble_scrverts(scr);
sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
return 1;
}
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;
}
}
}
/* test if screen vertices should be scaled */
static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
{
ScrVert *sv=NULL;
ScrArea *sa, *san;
int sizex, sizey;
float facx, facy, tempf, min[2], max[2];
/* calculate size */
min[0]= min[1]= 10000.0f;
max[0]= max[1]= 0.0f;
for(sv= sc->vertbase.first; sv; sv= sv->next) {
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);
}
/* always make 0.0 left under */
for(sv= sc->vertbase.first; sv; sv= sv->next) {
sv->vec.x -= min[0];
sv->vec.y -= min[1];
}
sizex= max[0]-min[0];
sizey= max[1]-min[1];
if(sizex!= winsizex || sizey!= winsizey) {
facx= winsizex;
facx/= (float)sizex;
facy= winsizey;
facy/= (float)sizey;
/* make sure it fits! */
for(sv= sc->vertbase.first; sv; sv= sv->next) {
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, winsizex);
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, winsizey);
}
}
/* test for collapsed areas. This could happen in some blender version... */
for(sa= sc->areabase.first; sa; sa= san) {
san= sa->next;
if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3)
screen_delarea(sc, sa);
}
/* make each window at least HEADERY high */
for(sa= sc->areabase.first; sa; sa= sa->next) {
int headery= HEADERY+1;
if(sa->v1->vec.y+headery > sa->v2->vec.y) {
/* lower edge */
ScrEdge *se= screen_findedge(sc, sa->v4, sa->v1);
if(se && sa->v1!=sa->v2 ) {
int yval;
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;
}
}
}
}
}
/* *********************** DRAWING **************************************** */
#define SCR_BACK 0.55
#define SCR_ROUND 12
/* draw vertical shape visualising future joining (left as well
* right direction of future joining) */
static void draw_horizontal_join_shape(ScrArea *sa, char dir)
{
vec2f points[10];
short i;
float w, h;
float width = sa->v3->vec.x - sa->v1->vec.x;
float height = sa->v3->vec.y - sa->v1->vec.y;
if(height<width) {
h = height/8;
w = height/4;
}
else {
h = width/8;
w = width/4;
}
points[0].x = sa->v1->vec.x;
points[0].y = sa->v1->vec.y + height/2;
points[1].x = sa->v1->vec.x;
points[1].y = sa->v1->vec.y;
points[2].x = sa->v4->vec.x - w;
points[2].y = sa->v4->vec.y;
points[3].x = sa->v4->vec.x - w;
points[3].y = sa->v4->vec.y + height/2 - 2*h;
points[4].x = sa->v4->vec.x - 2*w;
points[4].y = sa->v4->vec.y + height/2;
points[5].x = sa->v4->vec.x - w;
points[5].y = sa->v4->vec.y + height/2 + 2*h;
points[6].x = sa->v3->vec.x - w;
points[6].y = sa->v3->vec.y;
points[7].x = sa->v2->vec.x;
points[7].y = sa->v2->vec.y;
points[8].x = sa->v4->vec.x;
points[8].y = sa->v4->vec.y + height/2 - h;
points[9].x = sa->v4->vec.x;
points[9].y = sa->v4->vec.y + height/2 + h;
if(dir=='l') {
/* when direction is left, then we flip direction of arrow */
float cx = sa->v1->vec.x + width;
for(i=0;i<10;i++) {
points[i].x -= cx;
points[i].x = -points[i].x;
points[i].x += sa->v1->vec.x;
}
}
glBegin(GL_POLYGON);
for(i=0;i<5;i++)
glVertex2f(points[i].x, points[i].y);
glEnd();
glBegin(GL_POLYGON);
for(i=4;i<8;i++)
glVertex2f(points[i].x, points[i].y);
glVertex2f(points[0].x, points[0].y);
glEnd();
glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
}
/* draw vertical shape visualising future joining (up/down direction) */
static void draw_vertical_join_shape(ScrArea *sa, char dir)
{
vec2f points[10];
short i;
float w, h;
float width = sa->v3->vec.x - sa->v1->vec.x;
float height = sa->v3->vec.y - sa->v1->vec.y;
if(height<width) {
h = height/4;
w = height/8;
}
else {
h = width/4;
w = width/8;
}
points[0].x = sa->v1->vec.x + width/2;
points[0].y = sa->v3->vec.y;
points[1].x = sa->v2->vec.x;
points[1].y = sa->v2->vec.y;
points[2].x = sa->v1->vec.x;
points[2].y = sa->v1->vec.y + h;
points[3].x = sa->v1->vec.x + width/2 - 2*w;
points[3].y = sa->v1->vec.y + h;
points[4].x = sa->v1->vec.x + width/2;
points[4].y = sa->v1->vec.y + 2*h;
points[5].x = sa->v1->vec.x + width/2 + 2*w;
points[5].y = sa->v1->vec.y + h;
points[6].x = sa->v4->vec.x;
points[6].y = sa->v4->vec.y + h;
points[7].x = sa->v3->vec.x;
points[7].y = sa->v3->vec.y;
points[8].x = sa->v1->vec.x + width/2 - w;
points[8].y = sa->v1->vec.y;
points[9].x = sa->v1->vec.x + width/2 + w;
points[9].y = sa->v1->vec.y;
if(dir=='u') {
/* when direction is up, then we flip direction of arrow */
float cy = sa->v1->vec.y + height;
for(i=0;i<10;i++) {
points[i].y -= cy;
points[i].y = -points[i].y;
points[i].y += sa->v1->vec.y;
}
}
glBegin(GL_POLYGON);
for(i=0;i<5;i++)
glVertex2f(points[i].x, points[i].y);
glEnd();
glBegin(GL_POLYGON);
for(i=4;i<8;i++)
glVertex2f(points[i].x, points[i].y);
glVertex2f(points[0].x, points[0].y);
glEnd();
glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
}
/* draw join shape due to direction of joining */
static void draw_join_shape(ScrArea *sa, char dir)
{
if(dir=='u' || dir=='d')
draw_vertical_join_shape(sa, dir);
else
draw_horizontal_join_shape(sa, dir);
}
/* draw screen area darker with arrow (visualisation of future joining) */
static void scrarea_draw_shape_dark(ScrArea *sa, char dir)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glColor4ub(0, 0, 0, 50);
draw_join_shape(sa, dir);
glDisable(GL_BLEND);
}
/* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */
static void scrarea_draw_shape_light(ScrArea *sa, char dir)
{
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
glEnable(GL_BLEND);
/* value 181 was hardly computed: 181~105 */
glColor4ub(255, 255, 255, 50);
/* draw_join_shape(sa, dir); */
glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
glDisable(GL_BLEND);
}
/** screen edges drawing **/
static 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;
cpack(0x0);
/* right border area */
sdrawline(x2, y1, x2, y2);
/* left border area */
if(x1>0) { /* otherwise it draws the emboss of window over */
sdrawline(x1, y1, x1, y2);
}
/* top border area */
sdrawline(x1, y2, x2, y2);
/* bottom border area */
sdrawline(x1, y1, x2, y1);
}
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
{
bScreen *newsc;
if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */
/* make new empty screen: */
newsc= screen_add(win, sc->id.name+2);
/* copy all data */
screen_copy(newsc, sc);
return newsc;
}
void ED_screen_do_listen(wmWindow *win, wmNotifier *note)
{
/* generic notes */
switch(note->type) {
case WM_NOTE_WINDOW_REDRAW:
win->screen->do_draw= 1;
break;
case WM_NOTE_SCREEN_CHANGED:
win->screen->do_draw= win->screen->do_refresh= 1;
break;
case WM_NOTE_GESTURE_REDRAW:
win->screen->do_gesture= 1; /* XXX gestures are stored in window, draw per region... a bit weak? wait for proper composite? (ton) */
break;
}
}
void ED_screen_draw(wmWindow *win)
{
ScrArea *sa;
ScrArea *sa1=NULL;
ScrArea *sa2=NULL;
int dir = -1;
int dira = -1;
wm_subwindow_set(win, win->screen->mainwin);
for(sa= win->screen->areabase.first; sa; sa= sa->next) {
if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
drawscredge_area(sa);
}
/* blended join arrow */
if (sa1 && sa2) {
dir = area_getorientation(win->screen, sa1, sa2);
if (dir >= 0) {
switch(dir) {
case 0: /* W */
dir = 'r';
dira = 'l';
break;
case 1: /* N */
dir = 'd';
dira = 'u';
break;
case 2: /* E */
dir = 'l';
dira = 'r';
break;
case 3: /* S */
dir = 'u';
dira = 'd';
break;
}
}
scrarea_draw_shape_dark(sa2, dir);
scrarea_draw_shape_light(sa1, dira);
}
if(G.f & G_DEBUG) printf("draw screen\n");
win->screen->do_draw= 0;
}
/* make this screen usable */
/* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
{
ScrArea *sa;
rcti winrct= {0, win->sizex-1, 0, win->sizey-1};
screen_test_scale(win->screen, win->sizex, win->sizey);
if(win->screen->mainwin==0)
win->screen->mainwin= wm_subwindow_open(win, &winrct);
else
wm_subwindow_position(win, win->screen->mainwin, &winrct);
for(sa= win->screen->areabase.first; sa; sa= sa->next) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
ED_area_initialize(wm, win, sa);
}
if(G.f & G_DEBUG) printf("set screen\n");
win->screen->do_refresh= 0;
}
/* file read, set all screens, ... */
void ED_screens_initialize(wmWindowManager *wm)
{
wmWindow *win;
for(win= wm->windows.first; win; win= win->next) {
if(win->screen==NULL)
win->screen= G.main->screen.first;
ED_screen_refresh(wm, win);
}
}
void ED_region_exit(bContext *C, ARegion *ar)
{
ARegion *prevar= C->region;
C->region= ar;
WM_event_remove_handlers(C, &ar->handlers);
C->region= prevar;
}
void ED_area_exit(bContext *C, ScrArea *sa)
{
ScrArea *prevsa= C->area;
ARegion *ar;
C->area= sa;
for(ar= sa->regionbase.first; ar; ar= ar->next)
ED_region_exit(C, ar);
WM_event_remove_handlers(C, &sa->handlers);
C->area= prevsa;
}
void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
{
wmWindow *prevwin= C?C->window:NULL;
ScrArea *sa;
ARegion *ar;
C->window= window;
for(ar= screen->regionbase.first; ar; ar= ar->next)
ED_region_exit(C, ar);
for(sa= screen->areabase.first; sa; sa= sa->next)
ED_area_exit(C, sa);
WM_event_remove_handlers(C, &window->handlers);
C->window= prevwin;
}
/* called in wm_event_system.c. sets state var in screen */
void ED_screen_set_subwinactive(wmWindow *win)
{
if(win->screen) {
wmEvent *event= win->eventstate;
ScrArea *sa;
int oldswin= win->screen->subwinactive;
/* XXX prevent this call for modal menus now */
if(win->screen->regionbase.first)
return;
for(sa= win->screen->areabase.first; sa; sa= sa->next) {
if(event->x > sa->totrct.xmin && event->x < sa->totrct.xmax)
if(event->y > sa->totrct.ymin && event->y < sa->totrct.ymax)
break;
}
if(sa) {
ARegion *ar;
for(ar= sa->regionbase.first; ar; ar= ar->next) {
if(BLI_in_rcti(&ar->winrct, event->x, event->y))
win->screen->subwinactive= ar->swinid;
}
}
else
win->screen->subwinactive= win->screen->mainwin;
/* check for redraw headers */
if(oldswin!=win->screen->subwinactive) {
for(sa= win->screen->areabase.first; sa; sa= sa->next) {
ARegion *ar;
int do_draw= 0;
for(ar= sa->regionbase.first; ar; ar= ar->next)
if(ar->swinid==oldswin || ar->swinid==win->screen->subwinactive)
do_draw= 1;
if(do_draw) {
for(ar= sa->regionbase.first; ar; ar= ar->next)
if(ar->regiontype==RGN_TYPE_HEADER)
ar->do_draw= 1; /* XXX */
}
}
}
}
}
int ED_screen_area_active(const bContext *C)
{
if(C->screen && C->area) {
ARegion *ar;
for(ar= C->area->regionbase.first; ar; ar= ar->next)
if(ar->swinid == C->screen->subwinactive)
return 1;
}
return 0;
}