summaryrefslogtreecommitdiff
path: root/editcrse.c
diff options
context:
space:
mode:
Diffstat (limited to 'editcrse.c')
-rw-r--r--editcrse.c398
1 files changed, 398 insertions, 0 deletions
diff --git a/editcrse.c b/editcrse.c
new file mode 100644
index 0000000..c4f745f
--- /dev/null
+++ b/editcrse.c
@@ -0,0 +1,398 @@
+/*
+
+ 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 <ctype.h>
+
+
+/* ---------------------------------------- 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 */