summaryrefslogtreecommitdiff
path: root/editsect.c
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2011-06-09 13:57:32 +0000
committerIan C <ianc@noddybox.co.uk>2011-06-09 13:57:32 +0000
commitec32cf41f916fc34c03d2844684631bee39005ad (patch)
tree0ecd4b3a8602ba76df3b9395eb6c71c350d510df /editsect.c
Added copies of old numbered releases.0.02
Diffstat (limited to 'editsect.c')
-rw-r--r--editsect.c1612
1 files changed, 1612 insertions, 0 deletions
diff --git a/editsect.c b/editsect.c
new file mode 100644
index 0000000..d9085c5
--- /dev/null
+++ b/editsect.c
@@ -0,0 +1,1612 @@
+/*
+
+ 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 "util.h"
+
+#include <ctype.h>
+#include <math.h>
+
+
+/* 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;f<pick.sides;f++)
+ {
+ pick.p[f].x=(int)(pick.cx+(pick.r*sin(ang)));
+ pick.p[f].y=(int)(pick.cy+(pick.r*cos(ang)));
+ pick.p[f].x=SnapX(pick.p[f].x);
+ pick.p[f].y=SnapY(pick.p[f].y);
+ ang+=pick.ai;
+ }
+
+ for(f=0;f<pick.sides;f++)
+ GFX_line(MapToX(pick.p[f].x),MapToY(pick.p[f].y),
+ MapToX(pick.p[(f+1)%pick.sides].x),
+ MapToY(pick.p[(f+1)%pick.sides].y),WHITE);
+}
+
+
+/* ---------------------------------------- GENERATE VERTEX LIST FROM PICKDATA
+*/
+static List GenVertList(void)
+{
+ Object o;
+ EditVert *v;
+ List l;
+ int f,r,n;
+ int match;
+
+ for(f=0;f<pick.sides;f++)
+ {
+ match=TRUE;
+
+ while(match)
+ for(match=FALSE,r=0;(r<pick.sides)&&(!match);r++)
+ if (r!=f)
+ if ((pick.p[r].x==pick.p[f].x)&&
+ (pick.p[r].y==pick.p[f].y))
+ {
+ for(n=r;n<(pick.sides-1);n++)
+ {
+ pick.p[n].x=pick.p[n+1].x;
+ pick.p[n].y=pick.p[n+1].y;
+ }
+
+ pick.sides=MAX(pick.sides-1,0);
+
+ match=TRUE;
+ }
+ }
+
+ if (pick.sides<3)
+ return(NULL);
+
+ l=ListNew(sizeof(int));
+
+ for(f=0;f<pick.sides;f++)
+ {
+ v=Grab(sizeof(EditVert));
+ v->v.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 (vno<MapSize(vertex))
+ vmap=ReGrab(vmap,MapSize(vertex));
+
+ memset(vmap,FALSE,MapSize(vertex));
+}
+
+
+/* ---------------------------------------- SECTOR LINEDEF MAP UTILS
+*/
+static int lno=0;
+static char *lmap=NULL;
+
+static void InitLMAP(void)
+{
+ if (lno<MapSize(linedef))
+ lmap=ReGrab(lmap,MapSize(linedef));
+
+ memset(lmap,FALSE,MapSize(linedef));
+}
+
+
+/* ---------------------------------------- SECTOR CONTAINER ROUTINES
+*/
+
+/* Returns -1 for no sector
+*/
+int SectorHoldingPoint(int x,int y)
+{
+ Object *o;
+ int f;
+
+ TRACE;
+
+ for(f=0;f<MapSize(sector);f++)
+ {
+ o=MapElem(sector,f);
+
+ if ((o->data)&&(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;f<MapSize(linedef);f++)
+ {
+ match=FALSE;
+ l=GETLINE(f);
+
+ if (l)
+ {
+ if ((l->sr)&&(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;f<MapSize(sector);f++)
+ {
+ s=GETSECT(f);
+ SectorCalcContaining(f,s);
+ }
+}
+
+
+/* ---------------------------------------- SECTOR STYLING FUNCS
+*/
+static void ApplySectorStyle(EditSect *s, int flag,
+ DirName upper, DirName middle, DirName lower,
+ DirName floor, DirName ceiling)
+{
+ EditLine *l;
+ List track;
+ Iterator i,ti;
+ int ox,tw;
+ int *n;
+
+ TRACE;
+
+ tw=CalcTextureWidth(upper,middle,lower);
+
+ InitLMAP();
+
+ /* Dispose of two-sided linedefs wholly within the sector
+ */
+ i=ListIterator(s->all);
+
+ 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) && (y<vj->y)) ||
+ ((vj->y<=y) && (y<vi->y))) &&
+ (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;f<MapSize(sector);f++)
+ {
+ o=MapElem(sector,f);
+
+ if ((s=o->data))
+ {
+ 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;f<MapSize(sector);f++)
+ if ((o=MapElem(sector,f)))
+ if ((s=o->data)&&(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;f<MapSize(linedef);f++)
+ if ((l=GETLINE(f)))
+ if ((l->l.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.ceiling<s->s.floor)
+ s->s.ceiling+=8;
+ break;
+
+ case '>':
+ s->s.ceiling+=8;
+ if (s->s.ceiling<s->s.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));
+}
+
+
+ObjDesc *ObjectOverlaid_SECTOR(int x, int y, int *no)
+{
+ int n;
+ EditSect *s;
+ ObjDesc *od;
+ int f;
+
+ TRACE;
+
+ od=NULL;
+
+ n=0;
+
+ for(f=0;f<MapSize(sector);f++)
+ {
+ s=GETSECT(f);
+
+ if ((s)&&(PositionOnObject_SECTOR(x,y,s)))
+ {
+ n++;
+ od=ReGrab(od,sizeof(ObjDesc)*n);
+ od[n-1].no=f;
+
+ sprintf(od[n-1].detail,"%5d - %s (Tag %d)",f,
+ TrimStr(SectorName(s->s.special),50),
+ s->s.tag);
+ }
+ }
+
+ *no=n;
+ return(od);
+}
+
+
+/* END OF FILE */