home *** CD-ROM | disk | FTP | other *** search
- /*
- Doom Editor Utility, by Brendon Wyber and Raphaƫl Quinet.
-
- You are allowed to use any parts of this code in another program, as
- long as you give credits to the authors in the documentation and in
- the program itself. Read the file README.1ST for more information.
-
- This program comes with absolutely no warranty.
-
- OBJECTS.C - object handling routines.
- */
-
- /* the includes */
- #include "deu.h"
- #include "levels.h"
-
- /* the global variables */
- char DefaultWallTexture[ 9] = "STARTAN3";
- char DefaultFloorTexture[ 9] = "FLOOR4_8";
- char DefaultCeilingTexture[ 9] = "CEIL3_5";
- int DefaultFloorHeight = 0;
- int DefaultCeilingHeight = 400;
-
-
- /*
- highlight the selected objects
- */
-
- void HighlightSelection( int objtype, SelPtr list) /* SWAP! */
- {
- SelPtr cur;
-
- if (list == NULL)
- return;
- for (cur = list; cur; cur = cur->next)
- HighlightObject( objtype, cur->objnum, GREEN);
- }
-
-
-
- /*
- test if an object is in the selection list
- */
-
- Bool IsSelected( SelPtr list, int objnum)
- {
- SelPtr cur;
-
- for (cur = list; cur; cur = cur->next)
- if (cur->objnum == objnum)
- return TRUE;
- return FALSE;
- }
-
-
-
- /*
- add an object to the selection list
- */
-
- void SelectObject( SelPtr *list, int objnum)
- {
- SelPtr cur;
-
-
- if (objnum < 0)
- ProgError( "BUG: SelectObject called with %d", objnum);
- cur = GetMemory( sizeof( struct SelectionList));
- cur->next = *list;
- cur->objnum = objnum;
- *list = cur;
- }
-
-
-
- /*
- remove an object from the selection list
- */
-
- void UnSelectObject( SelPtr *list, int objnum)
- {
- SelPtr cur, prev;
-
- if (objnum < 0)
- ProgError( "BUG: UnSelectObject called with %d", objnum);
- prev = NULL;
- cur = *list;
- while (cur)
- {
- if (cur->objnum == objnum)
- {
- if (prev)
- prev->next = cur->next;
- else
- *list = cur->next;
- FreeMemory( cur);
- if (prev)
- cur = prev->next;
- else
- cur = NULL;
- }
- else
- {
- prev = cur;
- cur = cur->next;
- }
- }
- }
-
-
-
- /*
- forget the selection list
- */
-
- void ForgetSelection( SelPtr *list)
- {
- SelPtr cur, prev;
-
- cur = *list;
- while (cur)
- {
- prev = cur;
- cur = cur->next;
- FreeMemory( prev);
- }
- *list = NULL;
- }
-
-
-
- /*
- get the number of objets of a given type minus one
- */
- int GetMaxObjectNum( int objtype)
- {
- switch (objtype)
- {
- case OBJ_THINGS:
- return NumThings - 1;
- case OBJ_LINEDEFS:
- return NumLineDefs - 1;
- case OBJ_SIDEDEFS:
- return NumSideDefs - 1;
- case OBJ_VERTEXES:
- return NumVertexes - 1;
- case OBJ_SEGS:
- return NumSegs - 1;
- case OBJ_SSECTORS:
- return NumSSectors - 1;
- case OBJ_SECTORS:
- return NumSectors - 1;
- }
- return -1;
- }
-
-
- /*
- check if there is something of interest inside the given box
- */
-
- int GetCurObject( int objtype, int x0, int y0, int x1, int y1) /* SWAP! */
- {
- int n, m, cur, curx;
- int lx0, ly0, lx1, ly1, yy;
- int midx, midy;
-
- cur = -1;
- if (x1 < x0)
- {
- n = x0;
- x0 = x1;
- x1 = n;
- }
- if (y1 < y0)
- {
- n = y0;
- y0 = y1;
- y1 = n;
- }
-
- switch (objtype)
- {
- case OBJ_THINGS:
- ObjectsNeeded( OBJ_THINGS, 0);
- for (n = 0; n < NumThings; n++)
- if (Things[ n].xpos >= x0 && Things[ n].xpos <= x1 && Things[ n].ypos >= y0 && Things[ n].ypos <= y1)
- {
- cur = n;
- break;
- }
- break;
- case OBJ_VERTEXES:
- ObjectsNeeded( OBJ_VERTEXES, 0);
- for (n = 0; n < NumVertexes; n++)
- if (Vertexes[ n].x >= x0 && Vertexes[ n].x <= x1 && Vertexes[ n].y >= y0 && Vertexes[ n].y <= y1)
- {
- cur = n;
- break;
- }
- break;
- case OBJ_LINEDEFS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
- for (n = 0; n < NumLineDefs; n++)
- {
- if (IsLineDefInside( n, x0, y0, x1, y1))
- {
- cur = n;
- break;
- }
- }
- break;
- case OBJ_SECTORS:
- /* hack, hack... I look for the first LineDef crossing an horizontal half-line drawn from the cursor */
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
- curx = MapMaxX + 1;
- cur = -1;
- midx = (x0 + x1) / 2;
- midy = (y0 + y1) / 2;
- for (n = 0; n < NumLineDefs; n++)
- if ((Vertexes[ LineDefs[ n].start].y > midy != (Vertexes[ LineDefs[ n].end].y > midy)))
- {
- lx0 = Vertexes[ LineDefs[ n].start].x;
- ly0 = Vertexes[ LineDefs[ n].start].y;
- lx1 = Vertexes[ LineDefs[ n].end].x;
- ly1 = Vertexes[ LineDefs[ n].end].y;
- m = lx0 + (int) ((long) (midy - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
- if (m >= midx && m < curx)
- {
- curx = m;
- cur = n;
- }
- }
- /* now look if this LineDef has a SideDef bound to one sector */
- if (cur >= 0)
- {
- if (Vertexes[ LineDefs[ cur].start].y > Vertexes[ LineDefs[ cur].end].y)
- cur = LineDefs[ cur].sidedef1;
- else
- cur = LineDefs[ cur].sidedef2;
- if (cur >= 0)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- cur = SideDefs[ cur].sector;
- }
- else
- cur = -1;
- }
- else
- cur = -1;
- break;
- }
- return cur;
- }
-
-
-
- /*
- select all objects inside a given box
- */
-
- SelPtr SelectObjectsInBox( int objtype, int x0, int y0, int x1, int y1) /* SWAP! */
- {
- int n, m;
- SelPtr list;
-
- list = NULL;
- if (x1 < x0)
- {
- n = x0;
- x0 = x1;
- x1 = n;
- }
- if (y1 < y0)
- {
- n = y0;
- y0 = y1;
- y1 = n;
- }
-
- switch (objtype)
- {
- case OBJ_THINGS:
- ObjectsNeeded( OBJ_THINGS, 0);
- for (n = 0; n < NumThings; n++)
- if (Things[ n].xpos >= x0 && Things[ n].xpos <= x1 && Things[ n].ypos >= y0 && Things[ n].ypos <= y1)
- SelectObject( &list, n);
- break;
- case OBJ_VERTEXES:
- ObjectsNeeded( OBJ_VERTEXES, 0);
- for (n = 0; n < NumVertexes; n++)
- if (Vertexes[ n].x >= x0 && Vertexes[ n].x <= x1 && Vertexes[ n].y >= y0 && Vertexes[ n].y <= y1)
- SelectObject( &list, n);
- break;
- case OBJ_LINEDEFS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
- for (n = 0; n < NumLineDefs; n++)
- {
- /* the two ends of the line must be in the box */
- m = LineDefs[ n].start;
- if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
- continue;
- m = LineDefs[ n].end;
- if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
- continue;
- SelectObject( &list, n);
- }
- break;
- case OBJ_SECTORS:
- /* hack: select all sectors... */
- for (n = 0; n < NumSectors; n++)
- SelectObject( &list, n);
- /* ... then remove the unwanted ones from the list */
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, OBJ_VERTEXES, 0);
- for (n = 0; n < NumLineDefs; n++)
- {
- m = LineDefs[ n].start;
- if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
- {
- m = LineDefs[ n].sidedef1;
- if (m >= 0 && SideDefs[ m].sector >= 0)
- UnSelectObject( &list, SideDefs[ m].sector);
- m = LineDefs[ n].sidedef2;
- if (m >= 0 && SideDefs[ m].sector >= 0)
- UnSelectObject( &list, SideDefs[ m].sector);
- continue;
- }
- m = LineDefs[ n].end;
- if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
- {
- m = LineDefs[ n].sidedef1;
- if (m >= 0 && SideDefs[ m].sector >= 0)
- UnSelectObject( &list, SideDefs[ m].sector);
- m = LineDefs[ n].sidedef2;
- if (m >= 0 && SideDefs[ m].sector >= 0)
- UnSelectObject( &list, SideDefs[ m].sector);
- continue;
- }
- }
- break;
- }
- return list;
- }
-
-
-
- /*
- highlight the selected object
- */
-
- void HighlightObject( int objtype, int objnum, int color) /* SWAP! */
- {
- int n, m;
-
- /* use XOR mode : drawing any line twice erases it */
- setwritemode( XOR_PUT);
- SetColor( color);
- switch ( objtype)
- {
- case OBJ_THINGS:
- ObjectsNeeded( OBJ_THINGS, 0);
- m = (GetThingRadius( Things[ objnum].type) * 3) / 2;
- DrawMapLine( Things[ objnum].xpos - m, Things[ objnum].ypos - m, Things[ objnum].xpos - m, Things[ objnum].ypos + m);
- DrawMapLine( Things[ objnum].xpos - m, Things[ objnum].ypos + m, Things[ objnum].xpos + m, Things[ objnum].ypos + m);
- DrawMapLine( Things[ objnum].xpos + m, Things[ objnum].ypos + m, Things[ objnum].xpos + m, Things[ objnum].ypos - m);
- DrawMapLine( Things[ objnum].xpos + m, Things[ objnum].ypos - m, Things[ objnum].xpos - m, Things[ objnum].ypos - m);
- break;
- case OBJ_LINEDEFS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
- n = (Vertexes[ LineDefs[ objnum].start].x + Vertexes[ LineDefs[ objnum].end].x) / 2;
- m = (Vertexes[ LineDefs[ objnum].start].y + Vertexes[ LineDefs[ objnum].end].y) / 2;
- DrawMapLine( n, m, n + (Vertexes[ LineDefs[ objnum].end].y - Vertexes[ LineDefs[ objnum].start].y) / 3, m + (Vertexes[ LineDefs[ objnum].start].x - Vertexes[ LineDefs[ objnum].end].x) / 3);
- setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
- DrawMapVector( Vertexes[ LineDefs[ objnum].start].x, Vertexes[ LineDefs[ objnum].start].y,
- Vertexes[ LineDefs[ objnum].end].x, Vertexes[ LineDefs[ objnum].end].y);
- if (color != LIGHTRED && LineDefs[ objnum].tag > 0)
- {
- for (m = 0; m < NumSectors; m++)
- if (Sectors[ m].tag == LineDefs[ objnum].tag)
- HighlightObject( OBJ_SECTORS, m, LIGHTRED);
- }
- setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
- break;
- case OBJ_VERTEXES:
- ObjectsNeeded( OBJ_VERTEXES, 0);
- DrawMapLine( Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2, Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2);
- DrawMapLine( Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2, Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2);
- DrawMapLine( Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2, Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2);
- DrawMapLine( Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2, Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2);
- break;
- case OBJ_SECTORS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, OBJ_VERTEXES, 0);
- setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
- for (n = 0; n < NumLineDefs; n++)
- if (SideDefs[ LineDefs[ n].sidedef1].sector == objnum || SideDefs[ LineDefs[ n].sidedef2].sector == objnum)
- DrawMapLine( Vertexes[ LineDefs[ n].start].x, Vertexes[ LineDefs[ n].start].y,
- Vertexes[ LineDefs[ n].end].x, Vertexes[ LineDefs[ n].end].y);
- if (color != LIGHTRED && Sectors[ objnum].tag > 0)
- {
- for (m = 0; m < NumLineDefs; m++)
- if (LineDefs[ m].tag == Sectors[ objnum].tag)
- HighlightObject( OBJ_LINEDEFS, m, LIGHTRED);
- }
- setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
- break;
- }
- /* restore normal write mode */
- setwritemode( COPY_PUT);
- }
-
-
-
- /*
- delete an object
- */
-
- void DeleteObject( int objtype, int objnum) /* SWAP! */
- {
- SelPtr list;
-
- list = NULL;
- SelectObject( &list, objnum);
- DeleteObjects( objtype, &list);
- }
-
-
-
- /*
- delete a group of objects (*recursive*)
- */
-
- void DeleteObjects( int objtype, SelPtr *list) /* SWAP! */
- {
- int n, objnum;
- SelPtr cur;
-
- MadeChanges = TRUE;
- switch (objtype)
- {
- case OBJ_THINGS:
- ObjectsNeeded( OBJ_THINGS, 0);
- while (*list)
- {
- objnum = (*list)->objnum;
- /* delete the Thing */
- NumThings--;
- if (NumThings > 0)
- {
- for (n = objnum; n < NumThings; n++)
- Things[ n] = Things[ n + 1];
- Things = ResizeFarMemory( Things, NumThings * sizeof( struct Thing));
- }
- else
- {
- FreeFarMemory( Things);
- Things = NULL;
- }
- for (cur = (*list)->next; cur; cur = cur->next)
- if (cur->objnum > objnum)
- cur->objnum--;
- UnSelectObject( list, objnum);
- }
- break;
- case OBJ_VERTEXES:
- while (*list)
- {
- objnum = (*list)->objnum;
- /* delete the LineDefs bound to this Vertex and change the references */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (n = 0; n < NumLineDefs; n++)
- {
- if (LineDefs[ n].start == objnum || LineDefs[ n].end == objnum)
- DeleteObject( OBJ_LINEDEFS, n--);
- else
- {
- if (LineDefs[ n].start >= objnum)
- LineDefs[ n].start--;
- if (LineDefs[ n].end >= objnum)
- LineDefs[ n].end--;
- }
- }
- /* delete the Vertex */
- ObjectsNeeded( OBJ_VERTEXES, 0);
- NumVertexes--;
- if (NumVertexes > 0)
- {
- for (n = objnum; n < NumVertexes; n++)
- Vertexes[ n] = Vertexes[ n + 1];
- Vertexes = ResizeFarMemory( Vertexes, NumVertexes * sizeof( struct Vertex));
- }
- else
- {
- FreeFarMemory( Vertexes);
- Vertexes = NULL;
- }
- for (cur = (*list)->next; cur; cur = cur->next)
- if (cur->objnum > objnum)
- cur->objnum--;
- UnSelectObject( list, objnum);
- }
- break;
- case OBJ_LINEDEFS:
- while (*list)
- {
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- objnum = (*list)->objnum;
- /* delete the two SideDefs bound to this LineDef */
- if (LineDefs[ objnum].sidedef1 >= 0)
- {
- DeleteObject( OBJ_SIDEDEFS, LineDefs[ objnum].sidedef1);
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- }
- if (LineDefs[ objnum].sidedef2 >= 0)
- {
- DeleteObject( OBJ_SIDEDEFS, LineDefs[ objnum].sidedef2);
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- }
- /* delete the LineDef */
- NumLineDefs--;
- if (NumLineDefs > 0)
- {
- for (n = objnum; n < NumLineDefs; n++)
- LineDefs[ n] = LineDefs[ n + 1];
- LineDefs = ResizeFarMemory( LineDefs, NumLineDefs * sizeof( struct LineDef));
- }
- else
- {
- FreeFarMemory( LineDefs);
- LineDefs = NULL;
- }
- for (cur = (*list)->next; cur; cur = cur->next)
- if (cur->objnum > objnum)
- cur->objnum--;
- UnSelectObject( list, objnum);
- }
- break;
- case OBJ_SIDEDEFS:
- while (*list)
- {
- objnum = (*list)->objnum;
- /* change the LineDefs references */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (n = 0; n < NumLineDefs; n++)
- {
- if (LineDefs[ n].sidedef1 == objnum)
- LineDefs[ n].sidedef1 = -1;
- else if (LineDefs[ n].sidedef1 >= objnum)
- LineDefs[ n].sidedef1--;
- if (LineDefs[ n].sidedef2 == objnum)
- LineDefs[ n].sidedef2 = -1;
- else if (LineDefs[ n].sidedef2 >= objnum)
- LineDefs[ n].sidedef2--;
- }
- /* delete the SideDef */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- NumSideDefs--;
- if (NumSideDefs > 0)
- {
- for (n = objnum; n < NumSideDefs; n++)
- SideDefs[ n] = SideDefs[ n + 1];
- SideDefs = ResizeFarMemory( SideDefs, NumSideDefs * sizeof( struct SideDef));
- }
- else
- {
- FreeFarMemory( SideDefs);
- SideDefs = NULL;
- }
- for (cur = (*list)->next; cur; cur = cur->next)
- if (cur->objnum > objnum)
- cur->objnum--;
- UnSelectObject( list, objnum);
- }
- MadeMapChanges = TRUE;
- break;
- case OBJ_SECTORS:
- while (*list)
- {
- objnum = (*list)->objnum;
- /* delete the SideDefs bound to this Sector and change the references */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- for (n = 0; n < NumSideDefs; n++)
- if (SideDefs[ n].sector == objnum)
- DeleteObject( OBJ_SIDEDEFS, n--);
- else if (SideDefs[ n].sector >= objnum)
- SideDefs[ n].sector--;
- /* delete the Sector */
- ObjectsNeeded( OBJ_SECTORS, 0);
- NumSectors--;
- if (NumSectors > 0)
- {
- for (n = objnum; n < NumSectors; n++)
- Sectors[ n] = Sectors[ n + 1];
- Sectors = ResizeFarMemory( Sectors, NumSectors * sizeof( struct Sector));
- }
- else
- {
- FreeFarMemory( Sectors);
- Sectors = NULL;
- }
- for (cur = (*list)->next; cur; cur = cur->next)
- if (cur->objnum > objnum)
- cur->objnum--;
- UnSelectObject( list, objnum);
- }
- break;
- default:
- Beep();
- }
- }
-
-
-
- /*
- insert a new object
- */
-
- void InsertObject(int objtype, int copyfrom, int xpos, int ypos) /* SWAP! */
- {
- int last;
-
- ObjectsNeeded( objtype, 0);
- MadeChanges = TRUE;
- switch (objtype)
- {
- case OBJ_THINGS:
- last = NumThings++;
- if (last > 0)
- Things = ResizeFarMemory( Things, (unsigned long) NumThings * sizeof( struct Thing));
- else
- Things = GetFarMemory( sizeof( struct Thing));
- Things[ last].xpos = xpos;
- Things[ last].ypos = ypos;
- if (copyfrom >= 0)
- {
- Things[ last].type = Things[ copyfrom].type;
- Things[ last].angle = Things[ copyfrom].angle;
- Things[ last].when = Things[ copyfrom].when;
- }
- else
- {
- Things[ last].type = THING_TROOPER;
- Things[ last].angle = 0;
- Things[ last].when = 0x07;
- }
- break;
- case OBJ_VERTEXES:
- last = NumVertexes++;
- if (last > 0)
- Vertexes = ResizeFarMemory( Vertexes, (unsigned long) NumVertexes * sizeof( struct Vertex));
- else
- Vertexes = GetFarMemory( sizeof( struct Vertex));
- Vertexes[ last].x = xpos & ~7;
- Vertexes[ last].y = ypos & ~7;
- MadeMapChanges = TRUE;
- break;
- case OBJ_LINEDEFS:
- last = NumLineDefs++;
- if (last > 0)
- LineDefs = ResizeFarMemory( LineDefs, (unsigned long) NumLineDefs * sizeof( struct LineDef));
- else
- LineDefs = GetFarMemory( sizeof( struct LineDef));
- if (copyfrom >= 0)
- {
- LineDefs[ last].start = LineDefs[ copyfrom].start;
- LineDefs[ last].end = LineDefs[ copyfrom].end;
- LineDefs[ last].flags = LineDefs[ copyfrom].flags;
- LineDefs[ last].type = LineDefs[ copyfrom].type;
- LineDefs[ last].tag = LineDefs[ copyfrom].tag;
- }
- else
- {
- LineDefs[ last].start = 0;
- LineDefs[ last].end = NumVertexes - 1;
- LineDefs[ last].flags = 1;
- LineDefs[ last].type = 0;
- LineDefs[ last].tag = 0;
- }
- LineDefs[ last].sidedef1 = -1;
- LineDefs[ last].sidedef2 = -1;
- break;
- case OBJ_SIDEDEFS:
- /* SideDefs are added from the LineDefs menu, so "copyfrom" should always be -1. But I test it anyway. */
- last = NumSideDefs++;
- if (last > 0)
- SideDefs = ResizeFarMemory( SideDefs, (unsigned long) NumSideDefs * sizeof( struct SideDef));
- else
- SideDefs = GetFarMemory( sizeof( struct SideDef));
- if (copyfrom >= 0)
- {
- SideDefs[ last].xoff = SideDefs[ copyfrom].xoff;
- SideDefs[ last].yoff = SideDefs[ copyfrom].yoff;
- strncpy( SideDefs[ last].tex1, SideDefs[ copyfrom].tex1, 8);
- strncpy( SideDefs[ last].tex2, SideDefs[ copyfrom].tex2, 8);
- strncpy( SideDefs[ last].tex3, SideDefs[ copyfrom].tex3, 8);
- SideDefs[ last].sector = SideDefs[ copyfrom].sector;
- }
- else
- {
- SideDefs[ last].xoff = 0;
- SideDefs[ last].yoff = 0;
- strcpy( SideDefs[ last].tex1, "-");
- strcpy( SideDefs[ last].tex2, "-");
- strcpy( SideDefs[ last].tex3, DefaultWallTexture);
- SideDefs[ last].sector = NumSectors - 1;
- }
- MadeMapChanges = TRUE;
- break;
- case OBJ_SECTORS:
- last = NumSectors++;
- if (last > 0)
- Sectors = ResizeFarMemory( Sectors, (unsigned long) NumSectors * sizeof( struct Sector));
- else
- Sectors = GetFarMemory( sizeof( struct Sector));
- if (copyfrom >= 0)
- {
- Sectors[ last].floorh = Sectors[ copyfrom].floorh;
- Sectors[ last].ceilh = Sectors[ copyfrom].ceilh;
- strncpy( Sectors[ last].floort, Sectors[ copyfrom].floort, 8);
- strncpy( Sectors[ last].ceilt, Sectors[ copyfrom].ceilt, 8);
- Sectors[ last].light = Sectors[ copyfrom].light;
- Sectors[ last].special = Sectors[ copyfrom].special;
- Sectors[ last].tag = Sectors[ copyfrom].tag;
- }
- else
- {
- Sectors[ last].floorh = DefaultFloorHeight;
- Sectors[ last].ceilh = DefaultCeilingHeight;
- strncpy( Sectors[ last].floort, DefaultFloorTexture, 8);
- strncpy( Sectors[ last].ceilt, DefaultCeilingTexture, 8);
- Sectors[ last].light = 255;
- Sectors[ last].special = 0;
- Sectors[ last].tag = 0;
- }
- break;
- default:
- Beep();
- }
- }
-
-
-
- /*
- check if a (part of a) LineDef is inside a given block
- */
-
- Bool IsLineDefInside( int ldnum, int x0, int y0, int x1, int y1) /* SWAP - needs Vertexes & LineDefs */
- {
- int lx0 = Vertexes[ LineDefs[ ldnum].start].x;
- int ly0 = Vertexes[ LineDefs[ ldnum].start].y;
- int lx1 = Vertexes[ LineDefs[ ldnum].end].x;
- int ly1 = Vertexes[ LineDefs[ ldnum].end].y;
- int i;
-
- /* do you like mathematics? */
- if (lx0 >= x0 && lx0 <= x1 && ly0 >= y0 && ly0 <= y1)
- return TRUE; /* the LineDef start is entirely inside the square */
- if (lx1 >= x0 && lx1 <= x1 && ly1 >= y0 && ly1 <= y1)
- return TRUE; /* the LineDef end is entirely inside the square */
- if ((ly0 > y0) != (ly1 > y0))
- {
- i = lx0 + (int) ( (long) (y0 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
- if (i >= x0 && i <= x1)
- return TRUE; /* the LineDef crosses the y0 side (left) */
- }
- if ((ly0 > y1) != (ly1 > y1))
- {
- i = lx0 + (int) ( (long) (y1 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
- if (i >= x0 && i <= x1)
- return TRUE; /* the LineDef crosses the y1 side (right) */
- }
- if ((lx0 > x0) != (lx1 > x0))
- {
- i = ly0 + (int) ( (long) (x0 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0));
- if (i >= y0 && i <= y1)
- return TRUE; /* the LineDef crosses the x0 side (down) */
- }
- if ((lx0 > x1) != (lx1 > x1))
- {
- i = ly0 + (int) ( (long) (x1 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0));
- if (i >= y0 && i <= y1)
- return TRUE; /* the LineDef crosses the x1 side (up) */
- }
- return FALSE;
- }
-
-
-
- /*
- copy a group of objects to a new position
- */
-
- void CopyObjects( int objtype, SelPtr obj) /* SWAP! */
- {
- int n, m;
- SelPtr cur;
- SelPtr list1, list2;
- SelPtr ref1, ref2;
-
- if (obj == NULL)
- return;
- ObjectsNeeded( objtype, 0);
- /* copy the object(s) */
- switch (objtype)
- {
- case OBJ_THINGS:
- for (cur = obj; cur; cur = cur->next)
- {
- InsertObject( OBJ_THINGS, cur->objnum, Things[ cur->objnum].xpos, Things[ cur->objnum].ypos);
- cur->objnum = NumThings - 1;
- }
- MadeChanges = TRUE;
- break;
-
- case OBJ_VERTEXES:
- for (cur = obj; cur; cur = cur->next)
- {
- InsertObject( OBJ_VERTEXES, cur->objnum, Vertexes[ cur->objnum].x, Vertexes[ cur->objnum].y);
- cur->objnum = NumVertexes - 1;
- }
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- break;
-
- case OBJ_LINEDEFS:
- list1 = NULL;
- list2 = NULL;
- /* create the LineDefs */
- for (cur = obj; cur; cur = cur->next)
- {
- InsertObject( OBJ_LINEDEFS, cur->objnum, 0, 0);
- cur->objnum = NumLineDefs - 1;
- if (!IsSelected( list1, LineDefs[ cur->objnum].start))
- {
- SelectObject( &list1, LineDefs[ cur->objnum].start);
- SelectObject( &list2, LineDefs[ cur->objnum].start);
- }
- if (!IsSelected( list1, LineDefs[ cur->objnum].end))
- {
- SelectObject( &list1, LineDefs[ cur->objnum].end);
- SelectObject( &list2, LineDefs[ cur->objnum].end);
- }
- }
- /* create the Vertices */
- CopyObjects( OBJ_VERTEXES, list2);
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- /* update the references to the Vertexes */
- for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
- {
- for (cur = obj; cur; cur = cur->next)
- {
- if (ref1->objnum == LineDefs[ cur->objnum].start)
- LineDefs[ cur->objnum].start = ref2->objnum;
- if (ref1->objnum == LineDefs[ cur->objnum].end)
- LineDefs[ cur->objnum].end = ref2->objnum;
- }
- }
- ForgetSelection( &list1);
- ForgetSelection( &list2);
- break;
-
- case OBJ_SECTORS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
- list1 = NULL;
- list2 = NULL;
- /* create the LineDefs (and Vertices) */
- for (cur = obj; cur; cur = cur->next)
- {
- for (n = 0; n < NumLineDefs; n++)
- if ( (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
- || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
- && ! IsSelected( list1, n))
- {
- SelectObject( &list1, n);
- SelectObject( &list2, n);
- }
- }
- CopyObjects( OBJ_LINEDEFS, list2);
- /* create the SideDefs */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
- {
- if ((n = LineDefs[ ref1->objnum].sidedef1) >= 0)
- {
- InsertObject( OBJ_SIDEDEFS, n, 0, 0);
- n = NumSideDefs - 1;
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- LineDefs[ ref2->objnum].sidedef1 = n;
- }
- if ((m = LineDefs[ ref1->objnum].sidedef2) >= 0)
- {
- InsertObject( OBJ_SIDEDEFS, m, 0, 0);
- m = NumSideDefs - 1;
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- LineDefs[ ref2->objnum].sidedef2 = m;
- }
- ref1->objnum = n;
- ref2->objnum = m;
- }
- /* create the Sectors */
- for (cur = obj; cur; cur = cur->next)
- {
- InsertObject( OBJ_SECTORS, cur->objnum, 0, 0);
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
- {
- if (ref1->objnum >= 0 && SideDefs[ ref1->objnum].sector == cur->objnum)
- SideDefs[ ref1->objnum].sector = NumSectors - 1;
- if (ref2->objnum >= 0 && SideDefs[ ref2->objnum].sector == cur->objnum)
- SideDefs[ ref2->objnum].sector = NumSectors - 1;
- }
- cur->objnum = NumSectors - 1;
- }
- ForgetSelection( &list1);
- ForgetSelection( &list2);
- break;
- }
- }
-
-
-
- /*
- move a group of objects to a new position
- (must be called with obj = NULL before moving the objects)
- */
-
- Bool MoveObjectsToCoords( int objtype, SelPtr obj, int newx, int newy, int grid) /* SWAP! */
- {
- int n, m;
- int dx, dy;
- SelPtr cur, vertices;
- static int refx, refy;
-
- ObjectsNeeded( objtype, 0);
- if (grid > 0)
- {
- newx = (newx + grid / 2) & ~(grid - 1);
- newy = (newy + grid / 2) & ~(grid - 1);
- }
- else if (objtype == OBJ_VERTEXES)
- {
- newx = (newx + 4) & ~7;
- newy = (newy + 4) & ~7;
- }
-
- /* only update the reference point? */
- if (obj == NULL)
- {
- refx = newx;
- refy = newy;
- return TRUE;
- }
- /* compute the displacement */
- dx = newx - refx;
- dy = newy - refy;
- /* nothing to do? */
- if (dx == 0 && dy == 0)
- return FALSE;
-
- /* move the object(s) */
- switch (objtype)
- {
- case OBJ_THINGS:
- for (cur = obj; cur; cur = cur->next)
- {
- Things[ cur->objnum].xpos += dx;
- Things[ cur->objnum].ypos += dy;
- }
- refx = newx;
- refy = newy;
- MadeChanges = TRUE;
- break;
- case OBJ_VERTEXES:
- for (cur = obj; cur; cur = cur->next)
- {
- Vertexes[ cur->objnum].x += dx;
- Vertexes[ cur->objnum].y += dy;
- }
- refx = newx;
- refy = newy;
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- break;
- case OBJ_LINEDEFS:
- vertices = NULL;
- for (cur = obj; cur; cur = cur->next)
- {
- if (!IsSelected( vertices, LineDefs[ cur->objnum].start))
- SelectObject( &vertices, LineDefs[ cur->objnum].start);
- if (!IsSelected( vertices, LineDefs[ cur->objnum].end))
- SelectObject( &vertices, LineDefs[ cur->objnum].end);
- }
- MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
- ForgetSelection( &vertices);
- break;
- case OBJ_SECTORS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
- vertices = NULL;
- for (cur = obj; cur; cur = cur->next)
- {
- for (n = 0; n < NumLineDefs; n++)
- if (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
- || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
- {
- if (!IsSelected( vertices, LineDefs[ n].start))
- SelectObject( &vertices, LineDefs[ n].start);
- if (!IsSelected( vertices, LineDefs[ n].end))
- SelectObject( &vertices, LineDefs[ n].end);
- }
- }
- MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
- ForgetSelection( &vertices);
- break;
- }
- return TRUE;
- }
-
-
-
- /*
- get the coordinates (approx.) of an object
- */
-
- void GetObjectCoords( int objtype, int objnum, int *xpos, int *ypos) /* SWAP! */
- {
- int n, v1, v2, sd1, sd2;
- long accx, accy, num;
-
- switch (objtype)
- {
- case OBJ_THINGS:
- ObjectsNeeded( OBJ_THINGS, 0);
- *xpos = Things[ objnum].xpos;
- *ypos = Things[ objnum].ypos;
- break;
- case OBJ_VERTEXES:
- ObjectsNeeded( OBJ_VERTEXES, 0);
- *xpos = Vertexes[ objnum].x;
- *ypos = Vertexes[ objnum].y;
- break;
- case OBJ_LINEDEFS:
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- v1 = LineDefs[ objnum].start;
- v2 = LineDefs[ objnum].end;
- ObjectsNeeded( OBJ_VERTEXES, 0);
- *xpos = (Vertexes[ v1].x + Vertexes[ v2].x) / 2;
- *ypos = (Vertexes[ v1].y + Vertexes[ v2].y) / 2;
- break;
- case OBJ_SIDEDEFS:
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (n = 0; n < NumLineDefs; n++)
- if (LineDefs[ n].sidedef1 == objnum || LineDefs[ n].sidedef2 == objnum)
- {
- v1 = LineDefs[ n].start;
- v2 = LineDefs[ n].end;
- ObjectsNeeded( OBJ_VERTEXES, 0);
- *xpos = (Vertexes[ v1].x + Vertexes[ v2].x) / 2;
- *ypos = (Vertexes[ v1].y + Vertexes[ v2].y) / 2;
- return;
- }
- *xpos = (MapMinX + MapMaxX) / 2;
- *ypos = (MapMinY + MapMaxY) / 2;
- case OBJ_SECTORS:
- accx = 0L;
- accy = 0L;
- num = 0L;
- for (n = 0; n < NumLineDefs; n++)
- {
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- sd1 = LineDefs[ n].sidedef1;
- sd2 = LineDefs[ n].sidedef2;
- v1 = LineDefs[ n].start;
- v2 = LineDefs[ n].end;
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if ((sd1 >= 0 && SideDefs[ sd1].sector == objnum) || (sd2 >= 0 && SideDefs[ sd2].sector == objnum))
- {
- ObjectsNeeded( OBJ_VERTEXES, 0);
- /* if the Sector is closed, all Vertices will be counted twice */
- accx += (long) Vertexes[ v1].x;
- accy += (long) Vertexes[ v1].y;
- num++;
- accx += (long) Vertexes[ v2].x;
- accy += (long) Vertexes[ v2].y;
- num++;
- }
- }
- if (num > 0)
- {
- *xpos = (int) ((accx + num / 2L) / num);
- *ypos = (int) ((accy + num / 2L) / num);
- }
- else
- {
- *xpos = (MapMinX + MapMaxX) / 2;
- *ypos = (MapMinY + MapMaxY) / 2;
- }
- break;
- }
- }
-
-
-
- /*
- rotate and scale a group of objects around the center of gravity
- */
-
- void RotateAndScaleObjects( int objtype, SelPtr obj, double angle, double scale) /* SWAP! */
- {
- int n, m;
- int dx, dy;
- int centerx, centery;
- long accx, accy, num;
- SelPtr cur, vertices;
-
- if (obj == NULL)
- return;
- ObjectsNeeded( objtype, 0);
-
- switch (objtype)
- {
- case OBJ_THINGS:
- accx = 0L;
- accy = 0L;
- num = 0L;
- for (cur = obj; cur; cur = cur->next)
- {
- accx += (long) Things[ cur->objnum].xpos;
- accy += (long) Things[ cur->objnum].ypos;
- num++;
- }
- centerx = (int) ((accx + num / 2L) / num);
- centery = (int) ((accy + num / 2L) / num);
- for (cur = obj; cur; cur = cur->next)
- {
- dx = Things[ cur->objnum].xpos - centerx;
- dy = Things[ cur->objnum].ypos - centery;
- RotateAndScaleCoords( &dx, &dy, angle, scale);
- Things[ cur->objnum].xpos = centerx + dx;
- Things[ cur->objnum].ypos = centery + dy;
- }
- MadeChanges = TRUE;
- break;
- case OBJ_VERTEXES:
- accx = 0L;
- accy = 0L;
- num = 0L;
- for (cur = obj; cur; cur = cur->next)
- {
- accx += (long) Vertexes[ cur->objnum].x;
- accy += (long) Vertexes[ cur->objnum].y;
- num++;
- }
- centerx = (int) ((accx + num / 2L) / num);
- centery = (int) ((accy + num / 2L) / num);
- for (cur = obj; cur; cur = cur->next)
- {
- dx = Vertexes[ cur->objnum].x - centerx;
- dy = Vertexes[ cur->objnum].y - centery;
- RotateAndScaleCoords( &dx, &dy, angle, scale);
- Vertexes[ cur->objnum].x = (centerx + dx + 4) & ~7;
- Vertexes[ cur->objnum].y = (centery + dy + 4) & ~7;
- }
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- break;
- case OBJ_LINEDEFS:
- vertices = NULL;
- for (cur = obj; cur; cur = cur->next)
- {
- if (!IsSelected( vertices, LineDefs[ cur->objnum].start))
- SelectObject( &vertices, LineDefs[ cur->objnum].start);
- if (!IsSelected( vertices, LineDefs[ cur->objnum].end))
- SelectObject( &vertices, LineDefs[ cur->objnum].end);
- }
- RotateAndScaleObjects( OBJ_VERTEXES, vertices, angle, scale);
- ForgetSelection( &vertices);
- break;
- case OBJ_SECTORS:
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
- vertices = NULL;
- for (cur = obj; cur; cur = cur->next)
- {
- for (n = 0; n < NumLineDefs; n++)
- if (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
- || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
- {
- if (!IsSelected( vertices, LineDefs[ n].start))
- SelectObject( &vertices, LineDefs[ n].start);
- if (!IsSelected( vertices, LineDefs[ n].end))
- SelectObject( &vertices, LineDefs[ n].end);
- }
- }
- RotateAndScaleObjects( OBJ_VERTEXES, vertices, angle, scale);
- ForgetSelection( &vertices);
- break;
- }
- }
-
-
-
- /*
- find a free tag number
- */
-
- int FindFreeTag() /* SWAP! */
- {
- int tag, n;
- Bool ok;
-
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SECTORS, 0);
- tag = 1;
- ok = FALSE;
- while (! ok)
- {
- ok = TRUE;
- for (n = 0; n < NumLineDefs; n++)
- if (LineDefs[ n].tag == tag)
- {
- ok = FALSE;
- break;
- }
- if (ok)
- for (n = 0; n < NumSectors; n++)
- if (Sectors[ n].tag == tag)
- {
- ok = FALSE;
- break;
- }
- tag++;
- }
- return tag - 1;
- }
-
-
-
- /*
- flip one or several LineDefs
- */
-
- void FlipLineDefs( SelPtr obj, Bool swapvertices) /* SWAP! */
- {
- SelPtr cur;
- int tmp;
-
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (cur = obj; cur; cur = cur->next)
- {
- if (swapvertices)
- {
- /* swap starting and ending Vertices */
- tmp = LineDefs[ cur->objnum].end;
- LineDefs[ cur->objnum].end = LineDefs[ cur->objnum].start;
- LineDefs[ cur->objnum].start = tmp;
- }
- /* swap first and second SideDefs */
- tmp = LineDefs[ cur->objnum].sidedef1;
- LineDefs[ cur->objnum].sidedef1 = LineDefs[ cur->objnum].sidedef2;
- LineDefs[ cur->objnum].sidedef2 = tmp;
- }
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- }
-
-
-
- /*
- delete a vertex and join the two linedefs
- */
-
- void DeleteVerticesJoinLineDefs( SelPtr obj) /* SWAP! */
- {
- int lstart, lend, l;
- SelPtr cur;
- char msg[ 80];
-
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- while (obj)
- {
- cur = obj;
- obj = obj->next;
- lstart = -1;
- lend = -1;
- for (l = 0; l < NumLineDefs; l++)
- {
- if (LineDefs[ l].start == cur->objnum)
- {
- if (lstart == -1)
- lstart = l;
- else
- lstart = -2;
- }
- if (LineDefs[ l].end == cur->objnum)
- {
- if (lend == -1)
- lend = l;
- else
- lend = -2;
- }
- }
- if (lstart < 0 || lend < 0)
- {
- Beep();
- sprintf(msg, "Cannot delete Vertex #%d and join the LineDefs", cur->objnum);
- Notify( -1, -1, msg, "The Vertex must be the start of one LineDef and the end of another one");
- continue;
- }
- LineDefs[ lend].end = LineDefs[ lstart].end;
- DeleteObject( OBJ_LINEDEFS, lstart);
- DeleteObject( OBJ_VERTEXES, cur->objnum);
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- }
- }
-
-
-
- /*
- merge several vertices into one
- */
-
- void MergeVertices( SelPtr *list) /* SWAP! */
- {
- int v, l;
-
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- v = (*list)->objnum;
- UnSelectObject( list, v);
- if (*list == NULL)
- {
- Beep();
- Notify( -1, -1, "You must select at least two vertices", NULL);
- return;
- }
- /* change the LineDefs starts & ends */
- for (l = 0; l < NumLineDefs; l++)
- {
- if (IsSelected( *list, LineDefs[ l].start))
- {
- /* don't change a LineDef that has both ends on the same spot */
- if (!IsSelected( *list, LineDefs[ l].end) && LineDefs[ l].end != v)
- LineDefs[ l].start = v;
- }
- else if (IsSelected( *list, LineDefs[ l].end))
- {
- /* idem */
- if (LineDefs[ l].start != v)
- LineDefs[ l].end = v;
- }
- }
- /* delete the Vertices (and some LineDefs too) */
- DeleteObjects( OBJ_VERTEXES, list);
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- }
-
-
-
- /*
- check if some vertices should be merged into one
- */
-
- Bool CheckMergedVertices( SelPtr *list) /* SWAP! */
- {
- SelPtr ref, cur;
- Bool confirmed, redraw;
- int v, refv;
-
- ObjectsNeeded( OBJ_VERTEXES, 0);
- confirmed = FALSE;
- redraw = FALSE;
- ref = *list;
- while (ref)
- {
- refv = ref->objnum;
- ref = ref->next;
- /* check if there is a Vertex at the same position (same X and Y) */
- for (v = 0; v < NumVertexes; v++)
- if (v != refv && Vertexes[ refv].x == Vertexes[ v].x && Vertexes[ refv].y == Vertexes[ v].y)
- {
- redraw = TRUE;
- if (confirmed || Expert || Confirm( -1, -1, "Some Vertices occupy the same position", "Do you want to merge them into one?"))
- {
- /* don't ask for confirmation twice */
- confirmed = TRUE;
- /* merge the two vertices */
- cur = NULL;
- SelectObject( &cur, refv);
- SelectObject( &cur, v);
- MergeVertices( &cur);
- /* not useful but safer... */
- ObjectsNeeded( OBJ_VERTEXES, 0);
- /* update the references in the selection list */
- for (cur = *list; cur; cur = cur->next)
- if (cur->objnum > refv)
- cur->objnum = cur->objnum - 1;
- if (v > refv)
- v--;
- /* the old Vertex has been deleted */
- UnSelectObject( list, refv);
- /* select the new Vertex instead */
- if (!IsSelected( *list, v))
- SelectObject( list, v);
- break;
- }
- else
- return redraw;
- }
- }
- return redraw;
- }
-
-
-
- /*
- split one or more LineDefs in two, adding new Vertices in the middle
- */
-
- void SplitLineDefs( SelPtr obj) /* SWAP! */
- {
- SelPtr cur;
- int vstart, vend, sd;
-
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (cur = obj; cur; cur = cur->next)
- {
- vstart = LineDefs[ cur->objnum].start;
- vend = LineDefs[ cur->objnum].end;
- InsertObject( OBJ_VERTEXES, -1, (Vertexes[ vstart].x + Vertexes[ vend].x) / 2, (Vertexes[ vstart].y + Vertexes[ vend].y) / 2);
- InsertObject( OBJ_LINEDEFS, cur->objnum, 0, 0);
- LineDefs[ cur->objnum].end = NumVertexes - 1;
- LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
- sd = LineDefs[ cur->objnum].sidedef1;
- if (sd >= 0)
- {
- InsertObject( OBJ_SIDEDEFS, sd, 0, 0);
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
- }
- sd = LineDefs[ cur->objnum].sidedef2;
- if (sd >= 0)
- {
- InsertObject( OBJ_SIDEDEFS, sd, 0, 0);
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
- }
- }
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- }
-
-
-
- /*
- split a Sector in two, adding a new LineDef between the two Vertices
- */
-
- void SplitSector( int vertex1, int vertex2) /* SWAP! */
- {
- SelPtr llist;
- int curv, s, l, sd;
- char msg1[ 80], msg2[ 80];
-
- /* check if there is a Sector between the two Vertices (in the middle) */
- s = GetCurObject( OBJ_SECTORS, Vertexes[ vertex1].x, Vertexes[ vertex1].y, Vertexes[ vertex2].x, Vertexes[ vertex2].y);
- if (s < 0)
- {
- Beep();
- sprintf( msg1, "There is no Sector between Vertex #%d and Vertex #%d", vertex1, vertex2);
- Notify( -1, -1, msg1, NULL);
- return;
- }
- /* check if there is a closed path from vertex1 to vertex2, along the edge of the Sector s */
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
- llist = NULL;
- curv = vertex1;
- while (curv != vertex2)
- {
- for (l = 0; l < NumLineDefs; l++)
- {
- sd = LineDefs[ l].sidedef1;
- if (sd >= 0 && SideDefs[ sd].sector == s && LineDefs[ l].start == curv)
- {
- curv = LineDefs[ l].end;
- SelectObject( &llist, l);
- break;
- }
- sd = LineDefs[ l].sidedef2;
- if (sd >= 0 && SideDefs[ sd].sector == s && LineDefs[ l].end == curv)
- {
- curv = LineDefs[ l].start;
- SelectObject( &llist, l);
- break;
- }
- }
- if (l >= NumLineDefs)
- {
- Beep();
- sprintf( msg1, "Cannot find a closed path from Vertex #%d to Vertex #%d", vertex1, vertex2);
- if (curv == vertex1)
- sprintf( msg2, "There is no SideDef starting from Vertex #%d on Sector #%d", vertex1, s);
- else
- sprintf( msg2, "Check if Sector #%d is closed (cannot go past Vertex #%d)", s, curv);
- Notify( -1, -1, msg1, msg2);
- ForgetSelection( &llist);
- return;
- }
- if (curv == vertex1)
- {
- Beep();
- sprintf( msg1, "Vertex #%d is not on the same Sector (#%d) as Vertex #%d", vertex2, s, vertex1);
- Notify( -1, -1, msg1, NULL);
- ForgetSelection( &llist);
- return;
- }
- }
- /* now, the list of LineDefs for the new Sector is in llist */
-
- /* add the new Sector, LineDef and SideDefs */
- InsertObject( OBJ_SECTORS, s, 0, 0);
- InsertObject( OBJ_LINEDEFS, -1, 0, 0);
- LineDefs[ NumLineDefs - 1].start = vertex1;
- LineDefs[ NumLineDefs - 1].end = vertex2;
- LineDefs[ NumLineDefs - 1].flags = 4;
- InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
- SideDefs[ NumSideDefs - 1].sector = s;
- strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
- InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
- strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
- ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
- LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 2;
- LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
- /* bind all LineDefs in llist to the new Sector */
- while (llist)
- {
- sd = LineDefs[ llist->objnum].sidedef1;
- if (sd < 0 || SideDefs[ sd].sector != s)
- sd = LineDefs[ llist->objnum].sidedef2;
- SideDefs[ sd].sector = NumSectors - 1;
- UnSelectObject( &llist, llist->objnum);
- }
- MadeChanges = TRUE;
- MadeMapChanges = TRUE;
- }
-
-
-
- /*
- split two LineDefs, then split the Sector and add a new LineDef between the new Vertices
- */
-
- void SplitLineDefsAndSector( int linedef1, int linedef2) /* SWAP! */
- {
- SelPtr llist;
- int s1, s2, s3, s4;
- char msg[ 80];
-
- /* check if the two LineDefs are adjacent to the same Sector */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- s1 = LineDefs[ linedef1].sidedef1;
- s2 = LineDefs[ linedef1].sidedef2;
- s3 = LineDefs[ linedef2].sidedef1;
- s4 = LineDefs[ linedef2].sidedef2;
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (s1 >= 0)
- s1 = SideDefs[ s1].sector;
- if (s2 >= 0)
- s2 = SideDefs[ s2].sector;
- if (s3 >= 0)
- s3 = SideDefs[ s3].sector;
- if (s4 >= 0)
- s4 = SideDefs[ s4].sector;
- if ((s1 < 0 || (s1 != s3 && s1 != s4)) && (s2 < 0 || (s2 != s3 && s2 != s4)))
- {
- Beep();
- sprintf( msg, "LineDefs #%d and #%d are not adjacent to the same Sector", linedef1, linedef2);
- Notify( -1, -1, msg, NULL);
- return;
- }
- /* split the two LineDefs and create two new Vertices */
- llist = NULL;
- SelectObject( &llist, linedef1);
- SelectObject( &llist, linedef2);
- SplitLineDefs( llist);
- ForgetSelection( &llist);
- /* split the Sector and create a LineDef between the two Vertices */
- SplitSector( NumVertexes - 1, NumVertexes - 2);
- }
-
-
-
- /*
- turn a Sector into a door: change the LineDefs and SideDefs
- */
-
- void MakeDoorFromSector( int sector) /* SWAP! */
- {
- int sd1, sd2;
- int n, s;
- SelPtr ldok, ldflip, ld1s;
-
- ldok = NULL;
- ldflip = NULL;
- ld1s = NULL;
- s = 0;
- /* build lists of LineDefs that border the Sector */
- for (n = 0; n < NumLineDefs; n++)
- {
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- sd1 = LineDefs[ n].sidedef1;
- sd2 = LineDefs[ n].sidedef2;
- if (sd1 >= 0 && sd2 >= 0)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (SideDefs[ sd2].sector == sector)
- {
- SelectObject( &ldok, n); /* already ok */
- s++;
- }
- if (SideDefs[ sd1].sector == sector)
- {
- SelectObject( &ldflip, n); /* must be flipped */
- s++;
- }
- }
- else if (sd1 >= 0 && sd2 < 0)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (SideDefs[ sd1].sector == sector)
- SelectObject( &ld1s, n); /* wall (one-sided) */
- }
- }
- /* a normal door has two sides... */
- if (s < 2)
- {
- Beep();
- Notify( -1, -1, "The door must be connected to two other Sectors.", NULL);
- ForgetSelection( &ldok);
- ForgetSelection( &ldflip);
- ForgetSelection( &ld1s);
- return;
- }
- if ((s > 2) && !(Expert || Confirm( -1, -1, "The door will have more than two sides.", "Do you still want to create it?")))
- {
- ForgetSelection( &ldok);
- ForgetSelection( &ldflip);
- ForgetSelection( &ld1s);
- return;
- }
- /* flip the LineDefs that have the wrong orientation */
- if (ldflip != NULL)
- FlipLineDefs( ldflip, TRUE);
- /* merge the two selection lists */
- while (ldflip != NULL)
- {
- if (!IsSelected( ldok, ldflip->objnum))
- SelectObject( &ldok, ldflip->objnum);
- UnSelectObject( &ldflip, ldflip->objnum);
- }
- /* change the LineDefs and SideDefs */
- while (ldok != NULL)
- {
- /* give the "normal door" type and flags to the LineDef */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- n = ldok->objnum;
- LineDefs[ n].type = 1;
- LineDefs[ n].flags = 0x04;
- sd1 = LineDefs[ n].sidedef1;
- sd2 = LineDefs[ n].sidedef2;
- /* adjust the textures for the SideDefs */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (strncmp( SideDefs[ sd1].tex3, "-", 8))
- {
- if (!strncmp( SideDefs[ sd1].tex1, "-", 8))
- strncpy( SideDefs[ sd1].tex1, SideDefs[ sd1].tex3, 8);
- strncpy( SideDefs[ sd1].tex3, "-", 8);
- }
- if (!strncmp( SideDefs[ sd1].tex1, "-", 8))
- strncpy( SideDefs[ sd1].tex1, "BIGDOOR2", 8);
- strncpy( SideDefs[ sd2].tex3, "-", 8);
- UnSelectObject( &ldok, n);
- }
- while (ld1s != NULL)
- {
- /* give the "door side" flags to the LineDef */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- n = ld1s->objnum;
- LineDefs[ n].flags = 0x11;
- sd1 = LineDefs[ n].sidedef1;
- /* adjust the textures for the SideDef */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (!strncmp( SideDefs[ sd1].tex3, "-", 8))
- strncpy( SideDefs[ sd1].tex3, "DOORTRAK", 8);
- strncpy( SideDefs[ sd1].tex1, "-", 8);
- strncpy( SideDefs[ sd1].tex2, "-", 8);
- UnSelectObject( &ld1s, n);
- }
- /* adjust the ceiling height */
- ObjectsNeeded( OBJ_SECTORS, 0);
- Sectors[ sector].ceilh = Sectors[ sector].floorh;
- }
-
-
-
- /*
- turn a Sector into a lift: change the LineDefs and SideDefs
- */
-
- void MakeLiftFromSector( int sector) /* SWAP! */
- {
- int sd1, sd2;
- int n, s, tag;
- SelPtr ldok, ldflip, ld1s;
- SelPtr sect, curs;
- int minh, maxh;
-
- ldok = NULL;
- ldflip = NULL;
- ld1s = NULL;
- sect = NULL;
- /* build lists of LineDefs that border the Sector */
- for (n = 0; n < NumLineDefs; n++)
- {
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- sd1 = LineDefs[ n].sidedef1;
- sd2 = LineDefs[ n].sidedef2;
- if (sd1 >= 0 && sd2 >= 0)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (SideDefs[ sd2].sector == sector)
- {
- SelectObject( &ldok, n); /* already ok */
- s = SideDefs[ sd1].sector;
- if (s != sector && !IsSelected( sect, s))
- SelectObject( §, s);
- }
- if (SideDefs[ sd1].sector == sector)
- {
- SelectObject( &ldflip, n); /* will be flipped */
- s = SideDefs[ sd2].sector;
- if (s != sector && !IsSelected( sect, s))
- SelectObject( §, s);
- }
- }
- else if (sd1 >= 0 && sd2 < 0)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (SideDefs[ sd1].sector == sector)
- SelectObject( &ld1s, n); /* wall (one-sided) */
- }
- }
- /* there must be a way to go on the lift... */
- if (sect == NULL)
- {
- Beep();
- Notify( -1, -1, "The lift must be connected to at least one other Sector.", NULL);
- ForgetSelection( &ldok);
- ForgetSelection( &ldflip);
- ForgetSelection( &ld1s);
- return;
- }
- /* flip the LineDefs that have the wrong orientation */
- if (ldflip != NULL)
- FlipLineDefs( ldflip, TRUE);
- /* merge the two selection lists */
- while (ldflip != NULL)
- {
- if (!IsSelected( ldok, ldflip->objnum))
- SelectObject( &ldok, ldflip->objnum);
- UnSelectObject( &ldflip, ldflip->objnum);
- }
- /* find a free tag number */
- tag = FindFreeTag();
- /* find the minimum altitude */
- ObjectsNeeded( OBJ_SECTORS, 0);
- minh = 32767;
- maxh = -32768;
- for (curs = sect; curs; curs = curs->next)
- {
- if (Sectors[ curs->objnum].floorh < minh)
- minh = Sectors[ curs->objnum].floorh;
- if (Sectors[ curs->objnum].floorh > maxh)
- maxh = Sectors[ curs->objnum].floorh;
- }
- ForgetSelection( §);
- /* change the Sector altitude if necessary */
- if (Sectors[ sector].floorh < maxh)
- Sectors[ sector].floorh = maxh;
- Sectors[ sector].tag = tag;
- /* change the LineDefs and SideDefs */
- while (ldok != NULL)
- {
- /* give the "lower lift" or "raise lift" type and flags to the LineDef */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- n = ldok->objnum;
- LineDefs[ n].type = 62; /* raise lift & switch for lower */
- LineDefs[ n].flags = 0x04;
- LineDefs[ n].tag = tag;
- sd1 = LineDefs[ n].sidedef1;
- sd2 = LineDefs[ n].sidedef2;
- /* adjust the textures for the SideDefs */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (strncmp( SideDefs[ sd1].tex3, "-", 8))
- {
- if (!strncmp( SideDefs[ sd1].tex2, "-", 8))
- strncpy( SideDefs[ sd1].tex2, SideDefs[ sd1].tex3, 8);
- strncpy( SideDefs[ sd1].tex3, "-", 8);
- }
- if (!strncmp( SideDefs[ sd1].tex2, "-", 8))
- strncpy( SideDefs[ sd1].tex2, "SHAWN2", 8);
- strncpy( SideDefs[ sd2].tex3, "-", 8);
- s = SideDefs[ sd1].sector;
- ObjectsNeeded( OBJ_SECTORS, 0);
- if (Sectors[ s].floorh > minh)
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (strncmp( SideDefs[ sd2].tex3, "-", 8))
- {
- if (!strncmp( SideDefs[ sd2].tex2, "-", 8))
- strncpy( SideDefs[ sd2].tex2, SideDefs[ sd1].tex3, 8);
- strncpy( SideDefs[ sd2].tex3, "-", 8);
- }
- if (!strncmp( SideDefs[ sd2].tex2, "-", 8))
- strncpy( SideDefs[ sd2].tex2, "SHAWN2", 8);
- }
- else
- {
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- strncpy( SideDefs[ sd2].tex2, "-", 8);
- }
- strncpy( SideDefs[ sd2].tex3, "-", 8);
- ObjectsNeeded( OBJ_SECTORS, 0);
- /* if the Sector is above the lift */
- if (Sectors[ s].floorh >= Sectors[ sector].floorh)
- {
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- LineDefs[ n].type = 88; /* lower lift */
- /* flip it, just for fun */
- curs = NULL;
- SelectObject( &curs, n);
- FlipLineDefs( curs, TRUE);
- ForgetSelection( &curs);
- }
- UnSelectObject( &ldok, n);
- }
- while (ld1s != NULL)
- {
- /* these are the lift walls (one-sided) */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- n = ld1s->objnum;
- LineDefs[ n].flags = 0x01;
- sd1 = LineDefs[ n].sidedef1;
- /* adjust the textures for the SideDef */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- if (!strncmp( SideDefs[ sd1].tex3, "-", 8))
- strncpy( SideDefs[ sd1].tex3, DefaultWallTexture, 8);
- strncpy( SideDefs[ sd1].tex1, "-", 8);
- strncpy( SideDefs[ sd1].tex2, "-", 8);
- UnSelectObject( &ld1s, n);
- }
- }
-
-
-
- /*
- get the absolute height from which the textures are drawn
- */
-
- int GetTextureRefHeight( int sidedef) /* SWAP! */
- {
- int l, sector;
- int otherside;
-
- /* find the SideDef on the other side of the LineDef, if any */
- ObjectsNeeded( OBJ_LINEDEFS, 0);
- for (l = 0; l < NumLineDefs; l++)
- {
- if (LineDefs[ l].sidedef1 == sidedef)
- {
- otherside = LineDefs[ l].sidedef2;
- break;
- }
- if (LineDefs[ l].sidedef2 == sidedef)
- {
- otherside = LineDefs[ l].sidedef1;
- break;
- }
- }
- /* get the Sector number */
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- sector = SideDefs[ sidedef].sector;
- /* if the upper texture is displayed, then the reference is taken from the other Sector */
- if (otherside >= 0)
- {
- l = SideDefs[ otherside].sector;
- if (l > 0)
- {
- ObjectsNeeded( OBJ_SECTORS, 0);
- if (Sectors[ l].ceilh < Sectors[ sector].ceilh && Sectors[ l].ceilh > Sectors[ sector].floorh)
- sector = l;
- }
- }
- /* return the altitude of the ceiling */
- ObjectsNeeded( OBJ_SECTORS, 0);
- if (sector >= 0)
- return Sectors[ sector].ceilh; /* textures are drawn from the ceiling down */
- else
- return 0; /* yuck! */
- }
-
-
-
- /*
- Align all textures for the given SideDefs
- */
-
- void AlignTextures( SelPtr *sdlist) /* SWAP! */
- {
- int h, refh;
-
- if (*sdlist == NULL)
- return;
- /* get the reference height */
- refh = GetTextureRefHeight( (*sdlist)->objnum);
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- SideDefs[ (*sdlist)->objnum].yoff = 0;
- UnSelectObject( sdlist, (*sdlist)->objnum);
- /* adjust Y offset in all other SideDefs */
- while (*sdlist != NULL)
- {
- h = GetTextureRefHeight( (*sdlist)->objnum);
- ObjectsNeeded( OBJ_SIDEDEFS, 0);
- SideDefs[ (*sdlist)->objnum].yoff = (refh - h) % 128;
- UnSelectObject( sdlist, (*sdlist)->objnum);
- }
- MadeChanges = TRUE;
- }
-
-
-
- /* end of file */
-