/* 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 ------------------------------------------------------------------------- SECTOR interactive creation */ static const char rcs_id[]="$Id$"; #include "config.h" #include "globals.h" #include "editvar.h" #include "sectors.h" #include /* ---------------------------------------- SECTOR CREATION PRIVATE ROUTINES */ static void SwapTexture(DirName a, DirName b) { DirName t; strcpy(t,a); strcpy(a,b); strcpy(b,t); } static List ReverseList(List l) { Iterator i; List new; new=ListNew(sizeof(int)); i=ListIterator(l); while(i) { ListInsert(new,IteratorData(i)); i=IteratorNext(i); } return(new); } static List CopyList(List l) { Iterator i; List new; new=ListNew(sizeof(int)); i=ListIterator(l); while(i) { ListAppend(new,IteratorData(i)); i=IteratorNext(i); } return(new); } /* ---------------------------------------- SECTOR CREATION ROUTINES */ int CreateUnboundSector(int special,int floor,int ceiling,int light,int tag, DirName floor_t,DirName ceiling_t) { Object o; EditSect *s; int sn; TRACE; sn=MapSize(sector); s=Grab(sizeof(EditSect)); s->no=sn; s->s.special=special; s->s.floor=floor; s->s.ceiling=ceiling; s->s.light=light; strcpy(s->s.floor_t,floor_t); strcpy(s->s.ceiling_t,ceiling_t); s->v=ListNew(sizeof(Short)); s->sr=ListNew(sizeof(EditLine *)); s->sl=ListNew(sizeof(EditLine *)); s->all=ListNew(sizeof(EditLine *)); s->min_x=s->min_y=s->max_x=s->max_y=0; o.select=SELECT_NONE; o.data=s; MapAdd(sector,sn,&o); return(sn); } int CreateSector(List in_v) { List v; Iterator i; int *f; int from; int to; int type; int flag; int two; int first; int sect; int wr,wl; int oxr,oxl; DirName sr_upper,sr_middle,sr_lower; DirName sl_upper,sl_middle,sl_lower; EditSect *s; EditVert *v1,*v2; int special,floor,ceiling,light; int in_floor,in_ceiling,in_light; DirName floor_t,ceiling_t; int in_sector,new_sec; int swap; int nl; int style_flag; List left_offset; TRACE; /* Check enough vertexes */ if (ListSize(in_v)<3) { GuiInfoBox("ERROR","Need 3 or more vertices|" "to create a sector"); FullRedraw(); return(FALSE); } /* Check all points lie either inside the same sector or outside a sector */ in_sector=-1; i=ListIterator(in_v); f=IteratorData(i); v1=GETVERT(*f); in_sector=SectorHoldingPoint(v1->v.x,v1->v.y); i=IteratorNext(i); /* Check to see if the vertices are all inside the same sector. If some or all of the vertices lie outside the same sector then the sector is assumed to not be in another one */ while(i) { f=IteratorData(i); v1=GETVERT(*f); new_sec=SectorHoldingPoint(v1->v.x,v1->v.y); if ((in_sector!=-1)&&(new_sec!=in_sector)) in_sector=-1; i=IteratorNext(i); } if (in_sector!=-1) { s=GETSECT(in_sector); light=in_light=s->s.light; floor=in_floor=s->s.floor; ceiling=in_ceiling=s->s.ceiling; } else { s=NULL; light=in_light=default_light_level; floor=in_floor=default_floor_height; ceiling=in_ceiling=default_ceiling_height; } special=0; /* Now get the linedef and sector values */ if (!GetSectorValues(&type,&flag,&two, &floor,&ceiling,&light, in_floor,in_ceiling, &style_flag, floor_t,ceiling_t, sr_upper,sr_middle,sr_lower, sl_upper,sl_middle,sl_lower)) return(FALSE); /* See if the sector is inside another sector and see if the user wants the new sectors right sidedefs pointing out into the containing sector */ if (in_sector!=-1) swap=YesNo("Sector in another sector. Make RIGHT SIDEDEF point out?"); else swap=FALSE; /* Past here the user cannot cancel the create operation, so now create a copy of the vertex list (reversed if necessary) and reverse the textures as necessary */ if (swap) { if (two) { SwapTexture(sr_upper,sl_upper); SwapTexture(sr_middle,sl_middle); SwapTexture(sr_lower,sl_lower); } v=ReverseList(in_v); } else v=CopyList(in_v); /* Add either lower/upper unpegged according to the sector style flags */ if (style_flag&SSTYLE_UPPER_PEG) flag|=upper_peg_mask; if (style_flag&SSTYLE_LOWER_PEG) flag|=lower_peg_mask; /* Create list for left offsets if needed */ if (two) left_offset=ListNew(sizeof(int)); else left_offset=NULL; /* Calc texture widths and get a new sector number */ oxr=0; oxl=0; wr=CalcTextureWidth(sr_upper,sr_middle,sr_lower); if (two) wl=CalcTextureWidth (sl_upper,sl_middle,sl_lower); else wl=0; if (swap) { sect=in_sector; in_sector=CreateUnboundSector (special,floor,ceiling,light,0, floor_t,ceiling_t); } else sect=CreateUnboundSector (special,floor,ceiling,light,0, floor_t,ceiling_t); i=ListIterator(v); memcpy(&to,IteratorData(i),sizeof(int)); i=IteratorNext(i); first=to; while(i) { from=to; memcpy(&to,IteratorData(i),sizeof(int)); i=IteratorNext(i); nl=CreateNewLinedef (from,to, flag,type,0,two, oxr,0,sect, sr_upper,sr_middle,sr_lower, oxl,0,in_sector, sl_upper,sl_middle,sl_lower); v1=GETVERT(from); v2=GETVERT(to); IntListUniqAdd(v1->l,nl); IntListUniqAdd(v2->l,nl); if (wr) oxr=(oxr+Len(v1->v.x,v1->v.y, v2->v.x,v2->v.y))%wr; /* The left sidedef has the offsets coming from the opposite direction so have to be applied in reverse once all the lines have been created. Damn, wish I'd realised that earlier */ if (two) ListInsert(left_offset,&nl); } /* Create the line to close the polygon */ nl=CreateNewLinedef(to,first, flag,type,0,two, oxr,0,sect, sr_upper,sr_middle,sr_lower, oxl,0,in_sector, sl_upper,sl_middle,sl_lower); v1=GETVERT(to); v2=GETVERT(first); IntListUniqAdd(v1->l,nl); IntListUniqAdd(v2->l,nl); if (two) ListInsert(left_offset,&nl); /* Apply the left offsets */ if (two) { EditLine *l; i=ListIterator(left_offset); while(i) { f=IteratorData(i); l=GETLINE(*f); if (wl) oxl=(oxl+Len(l->v[0]->v.x,l->v[0]->v.y, l->v[1]->v.x,l->v[1]->v.y))%wl; l->sl->x=oxl; i=IteratorNext(i); } ListClear(left_offset); } /* Calc sector bounds */ if (swap) s=GETSECT(in_sector); else s=GETSECT(sect); SectorCalcContainingAll(); SectorCalcBounding(s); ListClear(v); /* Check for mergeable LINEDEFS */ i=ListIterator(s->v); while(i) { Short *s; s=IteratorData(i); CheckMergeLinedef(GETVERT(*s)); i=IteratorNext(i); } /* Recalc containing in case LINEDEFS where merged */ SectorCalcContainingAll(); return(TRUE); } /* END OF FILE */