/* viDOOM - level editor for DOOM Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk) 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 ------------------------------------------------------------------------- Editor SECTOR definitions */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "sectors.h" #include "editvar.h" #include #include /* This is the data shared between the PickPoint() callback functions and the Create function */ typedef struct { int cx; int cy; Point p[64]; int dx; int dy; int r; double ai; int sides; } PickData; static PickData pick; /* This shows which LINEDEFs are drawn tagged */ static List hilite=NULL; /* ---------------------------------------- PickPoint() CALLBACKS */ static void DrawVertSet(int *x, int *y) { double ang; int dx,dy; int f; TRACE; pick.dx=*x; pick.dy=*y; dx=pick.cx-pick.dx; dy=pick.cy-pick.dy; /* Calc angle that the line is at */ if (dx==0) if (dy<0) ang=RAD(0); else ang=RAD(180); else if (dy==0) if (dx<0) ang=RAD(90); else ang=RAD(270); else { ang=atan((double)dx/(double)dy); if (dy>0) ang-=RAD(180); } /* Calc line len */ pick.r=Len(pick.cx,pick.cy,pick.dx,pick.dy); for(f=0;fv.x=pick.p[f].x; v->v.y=pick.p[f].y; v->l=ListNew(sizeof(int)); n=MapSize(vertex); o.select=SELECT_NONE; o.data=v; MapAdd(vertex,n,&o); ListAppend(l,&n); } return(l); } /* ---------------------------------------- PRIVATE UTILS */ static int SelectColour(int selmode) { TRACE; switch(selmode) { case SELECT_OVER: return(OVERCOL); break; case SELECT_SELECTED: return(SELCOL); break; default: return(SECTCOL); break; } } void DrawSector(EditSect *s, int col, int check_tag) { Iterator i; EditLine *l; TRACE; i=ListIterator(s->all); while(i) { memcpy(&l,IteratorData(i),sizeof(l)); if (!(check_tag)||(!tag_highlight)||(!InIntList(hilite,l->no))) MapLineD(l,col); i=IteratorNext(i); } } static void RemoveHighlights(void) { Iterator i; Object *o; EditLine *l; int *n; i=ListIterator(hilite); while(i) { n=IteratorData(i); if ((l=GETLINE(*n))) { if (l->sr->sector>=0) if ((o=MapElem(sector,l->sr->sector))) DrawSector(o->data,SelectColour(o->select),FALSE); if ((l->sl)&&(l->sl->sector>=0)) if ((o=MapElem(sector,l->sl->sector))) DrawSector(o->data,SelectColour(o->select),FALSE); } i=IteratorNext(i); } } static void SectorSelectionCentre(int *x,int *y) { int *f; EditSect *s; Iterator i; int min_x,min_y,max_x,max_y; TRACE; i=ListIterator(selected); min_x=99999; min_y=99999; max_x=-99999; max_y=-99999; while(i) { f=IteratorData(i); s=GETSECT(*f); min_x=MIN(s->min_x,min_x); min_y=MIN(s->min_y,min_y); max_x=MAX(s->max_x,max_x); max_y=MAX(s->max_y,max_y); i=IteratorNext(i); } *x=min_x+(max_x-min_x)/2; *y=min_y+(max_y-min_y)/2; } /* ---------------------------------------- SECTOR VECTOR MAP UTILS */ static int vno=0; static char *vmap=NULL; static void InitVMAP(void) { if (vnodata)&&(PositionOnObject_SECTOR(x,y,o->data))) return(f); } return(-1); } void SectorCalcContaining(int no,EditSect *s) { int f; EditLine *l; int match; TRACE; ListEmpty(s->v); ListEmpty(s->sr); ListEmpty(s->sl); ListEmpty(s->all); InitVMAP(); for(f=0;fsr)&&(l->sr->sector==no)) { ListAppend(s->sr,&l); ListAppend(s->all,&l); match=TRUE; } if ((l->sl)&&(l->sl->sector==no)) { if (!match) ListAppend(s->all,&l); ListAppend(s->sl,&l); match=TRUE; } if (match) { if (!vmap[l->l.from]) { ListAppend(s->v,&(l->l.from)); vmap[l->l.from]=TRUE; } if (!vmap[l->l.to]) { ListAppend(s->v,&(l->l.to)); vmap[l->l.to]=TRUE; } } } } } void SectorCalcContainingAll(void) { int f; EditSect *s; TRACE; for(f=0;fall); while(i) { memcpy(&l,IteratorData(i),sizeof(l)); if ((l->sl)&&(l->sl->sector==s->no)&&(l->sr->sector==s->no)) lmap[l->no]=TRUE; i=IteratorNext(i); } /* Set the floor and ceiling */ strcpy(s->s.floor_t,floor); strcpy(s->s.ceiling_t,ceiling); /* Now draw a trail through the linedefs, aligning textures as we go along */ i=ListIterator(s->all); while(i) { memcpy(&l,IteratorData(i),sizeof(l)); if (!lmap[l->no]) { track=TrackLinedef(l->no); ox=0; ti=ListIterator(track); while(ti) { n=IteratorData(ti); l=GETLINE(*n); if (((l->sr->sector==s->no)&&(flag&SSTYLE_FACING_IN))|| ((l->sr->sector!=s->no)&&(flag&SSTYLE_FACING_OUT))) { if (strcmp(l->sr->upper,empty_texture)) { strcpy(l->sr->upper,upper); if (flag&SSTYLE_UPPER_PEG) l->l.flags|=upper_peg_mask; else if (!(flag&SSTYLE_LEAVE_PEG)) l->l.flags&=~upper_peg_mask; } if (strcmp(l->sr->middle,empty_texture)) strcpy(l->sr->middle,middle); if (strcmp(l->sr->lower,empty_texture)) { strcpy(l->sr->lower,lower); if (flag&SSTYLE_LOWER_PEG) l->l.flags|=lower_peg_mask; else if (!(flag&SSTYLE_LEAVE_PEG)) l->l.flags&=~lower_peg_mask; } l->sr->x=ox; lmap[l->no]=TRUE; } if ((l->sl)&& (((l->sl->sector==s->no)&&(flag&SSTYLE_FACING_IN))|| ((l->sl->sector!=s->no)&&(flag&SSTYLE_FACING_OUT)))) { if (strcmp(l->sl->upper,empty_texture)) { strcpy(l->sl->upper,upper); if (flag&SSTYLE_UPPER_PEG) l->l.flags|=upper_peg_mask; else if (!(flag&SSTYLE_LEAVE_PEG)) l->l.flags&=~upper_peg_mask; } if (strcmp(l->sl->middle,empty_texture)) strcpy(l->sl->middle,middle); if (strcmp(l->sl->lower,empty_texture)) { strcpy(l->sl->lower,lower); if (flag&SSTYLE_LOWER_PEG) l->l.flags|=lower_peg_mask; else if (!(flag&SSTYLE_LEAVE_PEG)) l->l.flags&=~lower_peg_mask; } l->sl->x=ox; lmap[l->no]=TRUE; } ox=(ox+Len(l->v[0]->v.x,l->v[0]->v.y, l->v[1]->v.x,l->v[1]->v.y))%tw; ti=IteratorNext(ti); } ListClear(track); } i=IteratorNext(i); } } /* ---------------------------------------- GENERIC SECTOR FUNCS */ int PositionOnObject_SECTOR(int x,int y,void *data) { int cross; EditSect *s; EditLine *l; Vertex *vi,*vj; Iterator i; TRACE; s=data; if (BOXBOUND(x,y,s->min_x,s->min_y,s->max_x,s->max_y)) { cross=FALSE; i=ListIterator(s->all); while(i) { memcpy(&l,IteratorData(i),sizeof(l)); /* Linedefs that have a right and left sidedef pointing at the same sector are not counted */ if (!((l->sr)&&(l->sl)&&(l->sl->sector==l->sr->sector))) { vi=&(l->v[0]->v); vj=&(l->v[1]->v); /* This code is taken from comp.graphics.algorithms FAQ 2.03 */ if ((((vi->y<=y) && (yy)) || ((vj->y<=y) && (yy))) && (x < (vj->x - vi->x) * (y - vi->y) / (vj->y - vi->y) + vi->x)) cross=!cross; } i=IteratorNext(i); } return(cross); } else return(FALSE); } /* This code is kept as a semi-working base if the routine based on the comp.graphics.algorithm FAQ fails (this could be as I don't do it on a list of ordered vertexes as the original does - doing on a line basis should be the same though). */ int OLD_PositionOnObject_SECTOR(int x,int y,void *data) { int x_no; int y_no; EditSect *s; EditLine *l; Iterator i; TRACE; s=data; if (BOXBOUND(x,y,s->min_x,s->min_y,s->max_x,s->max_y)) { x_no=0; y_no=0; i=ListIterator(s->all); while(i) { memcpy(&l,IteratorData(i),sizeof(l)); /* Linedefs that have a right and left sidedef pointing at the same sector are not counted */ if (!((l->sr)&&(l->sl)&&(l->sl->sector==l->sr->sector))) { /* This is a bit (understatement) kludgy, but we do 2 line crossing checks, one in X and one in the Y direction. This way we can omit a lot of extra checking for lines bisecting shared vertexes and the like. */ if (LinesCross(s->min_x,y,x,y, l->v[0]->v.x,l->v[0]->v.y, l->v[1]->v.x,l->v[1]->v.y)) x_no++; if (LinesCross(x,s->min_y,x,y, l->v[0]->v.x,l->v[0]->v.y, l->v[1]->v.x,l->v[1]->v.y)) y_no++; } i=IteratorNext(i); } /* Odd number of crossed lines means we're in the sector */ return((x_no%2)||(y_no%2)); } else return(FALSE); } void SelectBox_SECTOR(int x1,int y1,int x2,int y2) { Object *o; EditSect *s; int f; TRACE; for(f=0;fdata)) { if ((o->select!=SELECT_SELECTED)&& (BOXBOUND(s->min_x,s->min_y,x1,y1,x2,y2))&& (BOXBOUND(s->max_x,s->max_y,x1,y1,x2,y2))) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } } void SelectByType_SECTOR(void) { Object *o; EditSect *s; int id; int f; if ((id=SelectSector())!=SECTOR_NULLID) { ClearSelection(); for(f=0;fdata)&&(s->s.special==id)) { SetSelect(f,SELECT_SELECTED); ListAppend(selected,&f); } } } void DrawObject_SECTOR(void *data, int selmode) { static int drawn=FALSE; Object *o; EditSect *s; EditLine *l; int sel; int f; TRACE; if (!hilite) hilite=ListNew(sizeof(int)); s=data; /* If the current object has changed, remove the highlighted tag objects */ if ((current==-1)&&(drawn)) { drawn=FALSE; RemoveHighlights(); ListEmpty(hilite); } /* Draw tagged linedefs */ if ((tag_highlight)&&(current==s->no)) { RemoveHighlights(); ListEmpty(hilite); if (s->s.tag) { drawn=TRUE; for(f=0;fl.tag==s->s.tag)&&(LineOnDisplay(l))) { sel=FALSE; if (l->sr->sector>=0) if ((o=MapElem(sector,l->sr->sector))) sel=(o->select!=SELECT_NONE); if ((l->sl)&&(l->sl->sector>=0)) if ((o=MapElem(sector,l->sl->sector))) sel|=(o->select!=SELECT_NONE); if (!sel) { IntListUniqAdd(hilite,f); MapLineD(l,TAGCOL); } } } } DrawSector(s,SelectColour(selmode),TRUE); } void DrawObjectInfo_SECTOR(void) { EditSect *s; TRACE; if (!draw_current_info) return; if ((current!=-1)&&((s=GETSECT(current)))) GuiDrawInfoBox("SECTOR",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Sector Number : %-5d|" "Floor : %-5d|" "Ceiling : %-5d|" "Height : %-5d|" "Light : %-5d|" "Floor texture : %-10s|" "Ceiling texture : %-10s|" "Sector Type : %-30s|" "Tag : %-5d", current, s->s.floor, s->s.ceiling, s->s.ceiling-s->s.floor, s->s.light, s->s.floor_t, s->s.ceiling_t, SectorName(s->s.special), s->s.tag); else GuiDrawInfoBox("SECTOR",GUI_FLUSH_LEFT,GUI_FLUSH_LOWER,FALSE, "Sector Number : -|" "Floor : -|" "Ceiling : -|" "Height : -|" "Light : -|" "Floor texture : -|" "Ceiling texture : -|" "Sector Type : %-30s|" "Tag : -","-"); } void DrawObjectHeader_SECTOR(void) { if (tag_highlight) GFX_print(0,FH,WHITE,"Tag highlight: ON"); else GFX_print(0,FH,WHITE,"Tag highlight: OFF"); switch(sector_move) { case MOVE_ALL: GFX_print(SCRW/2,FH,WHITE,"Move mode: ALL"); break; case MOVE_LEFT: GFX_print(SCRW/2,FH,WHITE,"Move mode: LEFT"); break; case MOVE_RIGHT: GFX_print(SCRW/2,FH,WHITE,"Move mode: RIGHT"); break; } } void MoveObject_SECTOR(void) { GFXEvent ev; int omx,omy; int dmx,dmy; int done; Iterator i; Iterator i2; EditSect *s; EditLine *l; EditVert *v; List orig; int *f; Point p; List vert; int cancel; TRACE; omx=SnapX(XToMap(ms.x)); omy=SnapY(YToMap(ms.y)); GFX_bounce(); done=FALSE; cancel=FALSE; orig=ListNew(sizeof(Point)); vert=ListNew(sizeof(EditVert *)); InitVMAP(); i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); switch(sector_move) { case MOVE_ALL: i2=ListIterator(s->all); break; case MOVE_LEFT: i2=ListIterator(s->sl); break; case MOVE_RIGHT: default: i2=ListIterator(s->sr); break; } while(i2) { memcpy(&l,IteratorData(i2),sizeof(l)); if (!vmap[l->l.from]) { v=GETVERT(l->l.from); ListAppend(vert,&v); p.x=l->v[0]->v.x; p.y=l->v[0]->v.y; ListAppend(orig,&p); vmap[l->l.from]=TRUE; } if (!vmap[l->l.to]) { v=GETVERT(l->l.to); ListAppend(vert,&v); p.x=l->v[1]->v.x; p.y=l->v[1]->v.y; ListAppend(orig,&p); vmap[l->l.to]=TRUE; } i2=IteratorNext(i2); } i=IteratorNext(i); } while(!done) { GuiDrawInfoBox("Move SECTOR",GUI_FLUSH_RIGHT,GUI_FLUSH_LOWER,FALSE, "Left mouse button to place|ESC to cancel"); GFX_redraw(); GFX_await_input_full(&ev); switch(ev.type) { case GFX_KEY_EVENT: HandleMoveKey(ev.key,FALSE); /* Cancel the move */ if (ev.key.code==GFX_ESC) { cancel=TRUE; i=ListIterator(vert); i2=ListIterator(orig); while(i2) { memcpy(&v,IteratorData(i),sizeof(v)); memcpy(&p,IteratorData(i2),sizeof(Point)); v->v.x=p.x; v->v.y=p.y; i2=IteratorNext(i2); i=IteratorNext(i); } done=TRUE; dmx=0; dmy=0; } else { dmx=SnapX(XToMap(ms.x))-omx; dmy=SnapY(YToMap(ms.y))-omy; } break; case GFX_MOUSE_EVENT: memcpy(&ms,&ev.mouse,sizeof(ev.mouse)); if (ms.b&GFX_BUTLEFT) done=TRUE; dmx=SnapX(XToMap(ms.x))-omx; dmy=SnapY(YToMap(ms.y))-omy; break; default: dmx=0; dmy=0; break; } if ((dmx)||(dmy)) { i=ListIterator(vert); while(i) { memcpy(&v,IteratorData(i),sizeof(v)); v->v.x+=dmx; v->v.y+=dmy; i=IteratorNext(i); } omx=SnapX(XToMap(ms.x)); omy=SnapY(YToMap(ms.y)); FullRedraw(); } } ListClear(orig); ListClear(vert); if ((clear_on_move)&&(!cancel)) ClearSelection(); FullRedraw(); } void RotateObject_SECTOR(double angle) { int cx,cy; int x,y; int *f; Short *r; Iterator i,i2; EditSect *s; EditVert *v; TRACE; InitVMAP(); SectorSelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); i2=ListIterator(s->v); while(i2) { r=IteratorData(i2); v=GETVERT(*r); if (!vmap[*r]) { vmap[*r]=TRUE; x=v->v.x; y=v->v.y; Rotate(cx,cy,&x,&y,angle); v->v.x=x; v->v.y=y; } i2=IteratorNext(i2); } i=IteratorNext(i); } } void ScaleObject_SECTOR(double scale) { int cx,cy; int x,y; int *f; Short *r; Iterator i,i2; EditSect *s; EditVert *v; TRACE; InitVMAP(); SectorSelectionCentre(&cx,&cy); i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); i2=ListIterator(s->v); while(i2) { r=IteratorData(i2); v=GETVERT(*r); if (!vmap[*r]) { vmap[*r]=TRUE; x=v->v.x; y=v->v.y; Scale(cx,cy,&x,&y,scale); v->v.x=x; v->v.y=y; } i2=IteratorNext(i2); } i=IteratorNext(i); } } void SetTagObject_SECTOR(int tag) { int *f; Iterator i; EditSect *s; TRACE; i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.tag=tag; i=IteratorNext(i); } } void LocateObject_SECTOR(void *obj) { int cx,cy; EditSect *s; TRACE; s=obj; cx=s->min_x+(s->max_x-s->min_x)/2; cy=s->min_y+(s->max_y-s->min_y)/2; ox=cx-scale*SCRW/2; oy=cy+scale*SCRH/2; } void ObjectInsert_SECTOR(void) { # define SM_UNBOUND 1 # define SM_POLY 2 static PLAT_MENU sector_insert_menu[]= { {"Create unbound sector",SM_UNBOUND}, {"Create polygon",SM_POLY}, {NULL,GUI_CANCEL} }; TRACE; switch(GUI_menu("Sector",ms.x,ms.y,sector_insert_menu,GUI_CANCEL)) { case SM_UNBOUND: { int sec; sec=CreateUnboundSector(normal_sector,default_floor_height, default_ceiling_height,default_light_level, 0,empty_texture,empty_texture); GuiInfoBox("NOTICE","A sector number %d has been created.|" "SIDEDEFS will have to bound to the sector " "before it|becomes visible and edittable.",sec); FullRedraw(); break; } case SM_POLY: { static int last_sides=4; List sel; nosides_dialog[D_NOSIDES].data.i=last_sides; if (GUI_dialog("Create sector",D_NOSIDES_NO,nosides_dialog)) { pick.sides=nosides_dialog[D_NOSIDES].data.i; if ((pick.sides<3)||(pick.sides>64)) { GuiInfoBox("ERROR","Only enter a value between 3 and 64"); FullRedraw(); break; } else if (PickPoint("Select centre of new sector", &pick.cx,&pick.cy,NULL,NULL,NULL)) { pick.ai=RAD(360.0/pick.sides); if (PickPoint("Select the width and rotation " "of the sector",&pick.dx,&pick.dy, DrawVertSet,NULL,NULL)) { /* Merge identical vertices from the list and check that the vertices will not be dubious */ if ((sel=GenVertList())) { if (!CreateSector(sel)) { Iterator i; Object *o; EditVert *v; int *n; i=ListIterator(sel); while(i) { n=IteratorData(i); o=MapElem(vertex,*n); v=o->data; ListClear(v->l); Release(v); o->data=NULL; i=IteratorNext(i); } } else { FullRedraw(); last_sides=pick.sides; } ListClear(sel); } else { GuiInfoBox("ERROR","Shape makes no sense"); FullRedraw(); break; } } } } break; } default: break; } } void ObjectDelete_SECTOR(void) { TRACE; GuiInfoBox("NOTICE","Sector not deleted| |" "Sectors are automatically deleted|" "when saving the map if no LINEDEFs|" "are bound to it."); FullRedraw(); } void ObjectMenu_SECTOR(void) { Iterator i; EditSect *s; int *f; int cancel; TRACE; cancel=FALSE; switch(GUI_menu("Sector",ms.x,ms.y,sector_popup,GUI_CANCEL)) { case TM_FLOOR: s=SelHead(); sector_fl_dialog[D_SECTOR_FLOOR].data.i=s->s.floor; if (GUI_dialog("Floor height",D_SECTOR_FL_NO,sector_fl_dialog)) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.floor=sector_fl_dialog[D_SECTOR_FLOOR].data.i; i=IteratorNext(i); } i=IteratorClear(i); FullRedraw(); } break; case TM_CEILING: s=SelHead(); sector_ce_dialog[D_SECTOR_CEILING].data.i=s->s.ceiling; if (GUI_dialog("Ceiling height",D_SECTOR_CE_NO,sector_ce_dialog)) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.ceiling=sector_ce_dialog[D_SECTOR_CEILING].data.i; i=IteratorNext(i); } i=IteratorClear(i); FullRedraw(); } break; case TM_LIGHT: s=SelHead(); sector_li_dialog[D_SECTOR_LIGHT].data.i=s->s.light; if (GUI_dialog("Light level",D_SECTOR_LI_NO,sector_li_dialog)) { i=ListIterator(selected); sector_li_dialog[D_SECTOR_LIGHT].data.i= MIN(255,MAX(sector_li_dialog[D_SECTOR_LIGHT].data.i,0)); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.light=sector_li_dialog[D_SECTOR_LIGHT].data.i; i=IteratorNext(i); } i=IteratorClear(i); FullRedraw(); } break; case TM_TAG: s=SelHead(); tag_dialog[D_TAG].data.i=s->s.tag; if (GUI_dialog("Tag",D_TAG_NO,tag_dialog)) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.tag=tag_dialog[D_TAG].data.i; i=IteratorNext(i); } i=IteratorClear(i); FullRedraw(); } break; case TM_FLOOR_T: { DirName d; if ((GetFlat("Floor texture",d))) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); strcpy(s->s.floor_t,d); i=IteratorNext(i); } FullRedraw(); } break; } case TM_CEILING_T: { DirName d; if ((GetFlat("Ceiling texture",d))) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); strcpy(s->s.ceiling_t,d); i=IteratorNext(i); } FullRedraw(); } break; } case TM_TYPE: { int id; id=SelectSector(); if (id!=SECTOR_NULLID) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); s->s.special=id; i=IteratorNext(i); } FullRedraw(); } break; } case TM_STYLE: { int flag; DirName upper,middle,lower,floor,ceiling; if (ChooseSectorStyle(&flag,upper,middle,lower,floor,ceiling)) { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); ApplySectorStyle(s,flag,upper,middle,lower,floor,ceiling); i=IteratorNext(i); } } break; } case TM_MOVE: MoveObject_SECTOR(); break; case TM_DELETE: ObjectDelete_SECTOR(); break; default: cancel=TRUE; break; } if ((!cancel)&&(clear_on_menu)) { ClearSelection(); FullRedraw(); } } void ObjectKey_SECTOR(GFXKey k) { Iterator i; EditSect *s; int tmpsel; int *f; /* Check keys that need no objects */ if (k.code==GFX_ASCII) switch(toupper(k.ascii)) { case 'H': tag_highlight=!tag_highlight; FullRedraw(); break; case 'M': if (sector_move==MOVE_ALL) sector_move=MOVE_RIGHT; else if (sector_move==MOVE_RIGHT) sector_move=MOVE_LEFT; else if (sector_move==MOVE_LEFT) sector_move=MOVE_ALL; DrawHeader(); GFX_redraw(); break; default: break; } tmpsel=TmpAddCurrent(); if (ListSize(selected)==0) return; if (k.code!=GFX_ASCII) switch(k.code) { default: break; } else { i=ListIterator(selected); while(i) { f=IteratorData(i); s=GETSECT(*f); switch(toupper(k.ascii)) { case ',': s->s.floor-=8; if (s->s.floor>s->s.ceiling) s->s.floor+=8; break; case '.': s->s.floor+=8; if (s->s.floor>s->s.ceiling) s->s.floor-=8; break; case '<': s->s.ceiling-=8; if (s->s.ceilings.floor) s->s.ceiling+=8; break; case '>': s->s.ceiling+=8; if (s->s.ceilings.floor) s->s.ceiling-=8; break; case '-': s->s.light=MAX(0,s->s.light-16); break; case '+': s->s.light=MIN(255,s->s.light+16); break; default: break; } i=IteratorNext(i); } FullRedraw(); } if (tmpsel) ListEmpty(selected); } int ObjectHasTag_SECTOR(void *obj, int tag) { EditSect *s; return ((s=obj)&&(s->s.tag==tag)); } /* END OF FILE */