home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / DOOM / EDITOR / DEU51 / SOURCE / OBJECTS.C < prev    next >
C/C++ Source or Header  |  1994-04-27  |  55KB  |  1,940 lines

  1. /*
  2.    Doom Editor Utility, by Brendon Wyber and Raphaël Quinet.
  3.  
  4.    You are allowed to use any parts of this code in another program, as
  5.    long as you give credits to the authors in the documentation and in
  6.    the program itself.  Read the file README.1ST for more information.
  7.  
  8.    This program comes with absolutely no warranty.
  9.  
  10.    OBJECTS.C - object handling routines.
  11. */
  12.  
  13. /* the includes */
  14. #include "deu.h"
  15. #include "levels.h"
  16.  
  17. /* the global variables */
  18. char DefaultWallTexture[ 9] = "STARTAN3";
  19. char DefaultFloorTexture[ 9] = "FLOOR4_8";
  20. char DefaultCeilingTexture[ 9] = "CEIL3_5";
  21. int DefaultFloorHeight = 0;
  22. int DefaultCeilingHeight = 400;
  23.  
  24.  
  25. /*
  26.    highlight the selected objects
  27. */
  28.  
  29. void HighlightSelection( int objtype, SelPtr list) /* SWAP! */
  30. {
  31.    SelPtr cur;
  32.  
  33.    if (list == NULL)
  34.       return;
  35.    for (cur = list; cur; cur = cur->next)
  36.       HighlightObject( objtype, cur->objnum, GREEN);
  37. }
  38.  
  39.  
  40.  
  41. /*
  42.    test if an object is in the selection list
  43. */
  44.  
  45. Bool IsSelected( SelPtr list, int objnum)
  46. {
  47.    SelPtr cur;
  48.  
  49.    for (cur = list; cur; cur = cur->next)
  50.       if (cur->objnum == objnum)
  51.      return TRUE;
  52.    return FALSE;
  53. }
  54.  
  55.  
  56.  
  57. /*
  58.    add an object to the selection list
  59. */
  60.  
  61. void SelectObject( SelPtr *list, int objnum)
  62. {
  63.    SelPtr cur;
  64.  
  65.  
  66.    if (objnum < 0)
  67.       ProgError( "BUG: SelectObject called with %d", objnum);
  68.    cur = GetMemory( sizeof( struct SelectionList));
  69.    cur->next = *list;
  70.    cur->objnum = objnum;
  71.    *list = cur;
  72. }
  73.  
  74.  
  75.  
  76. /*
  77.    remove an object from the selection list
  78. */
  79.  
  80. void UnSelectObject( SelPtr *list, int objnum)
  81. {
  82.    SelPtr cur, prev;
  83.  
  84.    if (objnum < 0)
  85.       ProgError( "BUG: UnSelectObject called with %d", objnum);
  86.    prev = NULL;
  87.    cur = *list;
  88.    while (cur)
  89.    {
  90.       if (cur->objnum == objnum)
  91.       {
  92.      if (prev)
  93.         prev->next = cur->next;
  94.      else
  95.         *list = cur->next;
  96.      FreeMemory( cur);
  97.      if (prev)
  98.         cur = prev->next;
  99.      else
  100.         cur = NULL;
  101.       }
  102.       else
  103.       {
  104.      prev = cur;
  105.      cur = cur->next;
  106.       }
  107.    }
  108. }
  109.  
  110.  
  111.  
  112. /*
  113.    forget the selection list
  114. */
  115.  
  116. void ForgetSelection( SelPtr *list)
  117. {
  118.    SelPtr cur, prev;
  119.  
  120.    cur = *list;
  121.    while (cur)
  122.    {
  123.       prev = cur;
  124.       cur = cur->next;
  125.       FreeMemory( prev);
  126.    }
  127.    *list = NULL;
  128. }
  129.  
  130.  
  131.  
  132. /*
  133.    get the number of objets of a given type minus one
  134. */
  135. int GetMaxObjectNum( int objtype)
  136. {
  137.    switch (objtype)
  138.    {
  139.    case OBJ_THINGS:
  140.       return NumThings - 1;
  141.    case OBJ_LINEDEFS:
  142.       return NumLineDefs - 1;
  143.    case OBJ_SIDEDEFS:
  144.       return NumSideDefs - 1;
  145.    case OBJ_VERTEXES:
  146.       return NumVertexes - 1;
  147.    case OBJ_SEGS:
  148.       return NumSegs - 1;
  149.    case OBJ_SSECTORS:
  150.       return NumSSectors - 1;
  151.    case OBJ_SECTORS:
  152.       return NumSectors - 1;
  153.    }
  154.    return -1;
  155. }
  156.  
  157.  
  158. /*
  159.    check if there is something of interest inside the given box
  160. */
  161.  
  162. int GetCurObject( int objtype, int x0, int y0, int x1, int y1) /* SWAP! */
  163. {
  164.    int n, m, cur, curx;
  165.    int lx0, ly0, lx1, ly1, yy;
  166.    int midx, midy;
  167.  
  168.    cur = -1;
  169.    if (x1 < x0)
  170.    {
  171.       n = x0;
  172.       x0 = x1;
  173.       x1 = n;
  174.    }
  175.    if (y1 < y0)
  176.    {
  177.       n = y0;
  178.       y0 = y1;
  179.       y1 = n;
  180.    }
  181.  
  182.    switch (objtype)
  183.    {
  184.    case OBJ_THINGS:
  185.       ObjectsNeeded( OBJ_THINGS, 0);
  186.       for (n = 0; n < NumThings; n++)
  187.      if (Things[ n].xpos >= x0 && Things[ n].xpos <= x1 && Things[ n].ypos >= y0 && Things[ n].ypos <= y1)
  188.      {
  189.         cur = n;
  190.         break;
  191.      }
  192.       break;
  193.    case OBJ_VERTEXES:
  194.       ObjectsNeeded( OBJ_VERTEXES, 0);
  195.       for (n = 0; n < NumVertexes; n++)
  196.      if (Vertexes[ n].x >= x0 && Vertexes[ n].x <= x1 && Vertexes[ n].y >= y0 && Vertexes[ n].y <= y1)
  197.      {
  198.         cur = n;
  199.         break;
  200.      }
  201.       break;
  202.    case OBJ_LINEDEFS:
  203.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
  204.       for (n = 0; n < NumLineDefs; n++)
  205.       {
  206.      if (IsLineDefInside( n, x0, y0, x1, y1))
  207.      {
  208.         cur = n;
  209.         break;
  210.      }
  211.       }
  212.       break;
  213.    case OBJ_SECTORS:
  214.       /* hack, hack...  I look for the first LineDef crossing an horizontal half-line drawn from the cursor */
  215.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
  216.       curx = MapMaxX + 1;
  217.       cur = -1;
  218.       midx = (x0 + x1) / 2;
  219.       midy = (y0 + y1) / 2;
  220.       for (n = 0; n < NumLineDefs; n++)
  221.      if ((Vertexes[ LineDefs[ n].start].y > midy != (Vertexes[ LineDefs[ n].end].y > midy)))
  222.      {
  223.         lx0 = Vertexes[ LineDefs[ n].start].x;
  224.         ly0 = Vertexes[ LineDefs[ n].start].y;
  225.         lx1 = Vertexes[ LineDefs[ n].end].x;
  226.         ly1 = Vertexes[ LineDefs[ n].end].y;
  227.         m = lx0 + (int) ((long) (midy - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
  228.         if (m >= midx && m < curx)
  229.         {
  230.            curx = m;
  231.            cur = n;
  232.         }
  233.      }
  234.       /* now look if this LineDef has a SideDef bound to one sector */
  235.       if (cur >= 0)
  236.       {
  237.      if (Vertexes[ LineDefs[ cur].start].y > Vertexes[ LineDefs[ cur].end].y)
  238.         cur = LineDefs[ cur].sidedef1;
  239.      else
  240.         cur = LineDefs[ cur].sidedef2;
  241.      if (cur >= 0)
  242.      {
  243.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  244.         cur = SideDefs[ cur].sector;
  245.      }
  246.      else
  247.         cur = -1;
  248.       }
  249.       else
  250.      cur = -1;
  251.       break;
  252.    }
  253.    return cur;
  254. }
  255.  
  256.  
  257.  
  258. /*
  259.    select all objects inside a given box
  260. */
  261.  
  262. SelPtr SelectObjectsInBox( int objtype, int x0, int y0, int x1, int y1) /* SWAP! */
  263. {
  264.    int n, m;
  265.    SelPtr list;
  266.  
  267.    list = NULL;
  268.    if (x1 < x0)
  269.    {
  270.       n = x0;
  271.       x0 = x1;
  272.       x1 = n;
  273.    }
  274.    if (y1 < y0)
  275.    {
  276.       n = y0;
  277.       y0 = y1;
  278.       y1 = n;
  279.    }
  280.  
  281.    switch (objtype)
  282.    {
  283.    case OBJ_THINGS:
  284.       ObjectsNeeded( OBJ_THINGS, 0);
  285.       for (n = 0; n < NumThings; n++)
  286.      if (Things[ n].xpos >= x0 && Things[ n].xpos <= x1 && Things[ n].ypos >= y0 && Things[ n].ypos <= y1)
  287.         SelectObject( &list, n);
  288.       break;
  289.    case OBJ_VERTEXES:
  290.       ObjectsNeeded( OBJ_VERTEXES, 0);
  291.       for (n = 0; n < NumVertexes; n++)
  292.      if (Vertexes[ n].x >= x0 && Vertexes[ n].x <= x1 && Vertexes[ n].y >= y0 && Vertexes[ n].y <= y1)
  293.         SelectObject( &list, n);
  294.       break;
  295.    case OBJ_LINEDEFS:
  296.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
  297.       for (n = 0; n < NumLineDefs; n++)
  298.       {
  299.      /* the two ends of the line must be in the box */
  300.      m = LineDefs[ n].start;
  301.      if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
  302.         continue;
  303.      m = LineDefs[ n].end;
  304.      if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
  305.         continue;
  306.      SelectObject( &list, n);
  307.       }
  308.       break;
  309.    case OBJ_SECTORS:
  310.       /* hack: select all sectors... */
  311.       for (n = 0; n < NumSectors; n++)
  312.      SelectObject( &list, n);
  313.       /* ... then remove the unwanted ones from the list */
  314.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, OBJ_VERTEXES, 0);
  315.       for (n = 0; n < NumLineDefs; n++)
  316.       {
  317.      m = LineDefs[ n].start;
  318.      if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
  319.      {
  320.         m = LineDefs[ n].sidedef1;
  321.         if (m >= 0 && SideDefs[ m].sector >= 0)
  322.            UnSelectObject( &list, SideDefs[ m].sector);
  323.         m = LineDefs[ n].sidedef2;
  324.         if (m >= 0 && SideDefs[ m].sector >= 0)
  325.            UnSelectObject( &list, SideDefs[ m].sector);
  326.         continue;
  327.      }
  328.      m = LineDefs[ n].end;
  329.      if (Vertexes[ m].x < x0 || Vertexes[ m].x > x1 || Vertexes[ m].y < y0 || Vertexes[ m].y > y1)
  330.      {
  331.         m = LineDefs[ n].sidedef1;
  332.         if (m >= 0 && SideDefs[ m].sector >= 0)
  333.            UnSelectObject( &list, SideDefs[ m].sector);
  334.         m = LineDefs[ n].sidedef2;
  335.         if (m >= 0 && SideDefs[ m].sector >= 0)
  336.            UnSelectObject( &list, SideDefs[ m].sector);
  337.         continue;
  338.      }
  339.       }
  340.       break;
  341.    }
  342.    return list;
  343. }
  344.  
  345.  
  346.  
  347. /*
  348.    highlight the selected object
  349. */
  350.  
  351. void HighlightObject( int objtype, int objnum, int color) /* SWAP! */
  352. {
  353.    int  n, m;
  354.  
  355.    /* use XOR mode : drawing any line twice erases it */
  356.    setwritemode( XOR_PUT);
  357.    SetColor( color);
  358.    switch ( objtype)
  359.    {
  360.    case OBJ_THINGS:
  361.       ObjectsNeeded( OBJ_THINGS, 0);
  362.       m = (GetThingRadius( Things[ objnum].type) * 3) / 2;
  363.       DrawMapLine( Things[ objnum].xpos - m, Things[ objnum].ypos - m, Things[ objnum].xpos - m, Things[ objnum].ypos + m);
  364.       DrawMapLine( Things[ objnum].xpos - m, Things[ objnum].ypos + m, Things[ objnum].xpos + m, Things[ objnum].ypos + m);
  365.       DrawMapLine( Things[ objnum].xpos + m, Things[ objnum].ypos + m, Things[ objnum].xpos + m, Things[ objnum].ypos - m);
  366.       DrawMapLine( Things[ objnum].xpos + m, Things[ objnum].ypos - m, Things[ objnum].xpos - m, Things[ objnum].ypos - m);
  367.       break;
  368.    case OBJ_LINEDEFS:
  369.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_VERTEXES, 0);
  370.       n = (Vertexes[ LineDefs[ objnum].start].x + Vertexes[ LineDefs[ objnum].end].x) / 2;
  371.       m = (Vertexes[ LineDefs[ objnum].start].y + Vertexes[ LineDefs[ objnum].end].y) / 2;
  372.       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);
  373.       setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
  374.       DrawMapVector( Vertexes[ LineDefs[ objnum].start].x, Vertexes[ LineDefs[ objnum].start].y,
  375.              Vertexes[ LineDefs[ objnum].end].x, Vertexes[ LineDefs[ objnum].end].y);
  376.       if (color != LIGHTRED && LineDefs[ objnum].tag > 0)
  377.       {
  378.      for (m = 0; m < NumSectors; m++)
  379.         if (Sectors[ m].tag == LineDefs[ objnum].tag)
  380.            HighlightObject( OBJ_SECTORS, m, LIGHTRED);
  381.       }
  382.       setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  383.       break;
  384.    case OBJ_VERTEXES:
  385.       ObjectsNeeded( OBJ_VERTEXES, 0);
  386.       DrawMapLine( Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2, Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2);
  387.       DrawMapLine( Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2, Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2);
  388.       DrawMapLine( Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y + OBJSIZE * 2, Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2);
  389.       DrawMapLine( Vertexes[ objnum].x + OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2, Vertexes[ objnum].x - OBJSIZE * 2, Vertexes[ objnum].y - OBJSIZE * 2);
  390.       break;
  391.    case OBJ_SECTORS:
  392.       ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, OBJ_VERTEXES, 0);
  393.       setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
  394.       for (n = 0; n < NumLineDefs; n++)
  395.      if (SideDefs[ LineDefs[ n].sidedef1].sector == objnum || SideDefs[ LineDefs[ n].sidedef2].sector == objnum)
  396.         DrawMapLine( Vertexes[ LineDefs[ n].start].x, Vertexes[ LineDefs[ n].start].y,
  397.              Vertexes[ LineDefs[ n].end].x, Vertexes[ LineDefs[ n].end].y);
  398.       if (color != LIGHTRED && Sectors[ objnum].tag > 0)
  399.       {
  400.      for (m = 0; m < NumLineDefs; m++)
  401.         if (LineDefs[ m].tag == Sectors[ objnum].tag)
  402.            HighlightObject( OBJ_LINEDEFS, m, LIGHTRED);
  403.       }
  404.       setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  405.       break;
  406.    }
  407.    /* restore normal write mode */
  408.    setwritemode( COPY_PUT);
  409. }
  410.  
  411.  
  412.  
  413. /*
  414.    delete an object
  415. */
  416.  
  417. void DeleteObject( int objtype, int objnum) /* SWAP! */
  418. {
  419.    SelPtr list;
  420.  
  421.    list = NULL;
  422.    SelectObject( &list, objnum);
  423.    DeleteObjects( objtype, &list);
  424. }
  425.  
  426.  
  427.  
  428. /*
  429.    delete a group of objects (*recursive*)
  430. */
  431.  
  432. void DeleteObjects( int objtype, SelPtr *list) /* SWAP! */
  433. {
  434.    int    n, objnum;
  435.    SelPtr cur;
  436.  
  437.    MadeChanges = TRUE;
  438.    switch (objtype)
  439.    {
  440.    case OBJ_THINGS:
  441.       ObjectsNeeded( OBJ_THINGS, 0);
  442.       while (*list)
  443.       {
  444.      objnum = (*list)->objnum;
  445.      /* delete the Thing */
  446.      NumThings--;
  447.      if (NumThings > 0)
  448.      {
  449.         for (n = objnum; n < NumThings; n++)
  450.            Things[ n] = Things[ n + 1];
  451.         Things = ResizeFarMemory( Things, NumThings * sizeof( struct Thing));
  452.      }
  453.      else
  454.      {
  455.         FreeFarMemory( Things);
  456.         Things = NULL;
  457.      }
  458.      for (cur = (*list)->next; cur; cur = cur->next)
  459.         if (cur->objnum > objnum)
  460.            cur->objnum--;
  461.      UnSelectObject( list, objnum);
  462.       }
  463.       break;
  464.    case OBJ_VERTEXES:
  465.       while (*list)
  466.       {
  467.      objnum = (*list)->objnum;
  468.      /* delete the LineDefs bound to this Vertex and change the references */
  469.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  470.      for (n = 0; n < NumLineDefs; n++)
  471.      {
  472.         if (LineDefs[ n].start == objnum || LineDefs[ n].end == objnum)
  473.            DeleteObject( OBJ_LINEDEFS, n--);
  474.         else
  475.         {
  476.            if (LineDefs[ n].start >= objnum)
  477.           LineDefs[ n].start--;
  478.            if (LineDefs[ n].end >= objnum)
  479.           LineDefs[ n].end--;
  480.         }
  481.      }
  482.      /* delete the Vertex */
  483.      ObjectsNeeded( OBJ_VERTEXES, 0);
  484.      NumVertexes--;
  485.      if (NumVertexes > 0)
  486.      {
  487.         for (n = objnum; n < NumVertexes; n++)
  488.            Vertexes[ n] = Vertexes[ n + 1];
  489.         Vertexes = ResizeFarMemory( Vertexes, NumVertexes * sizeof( struct Vertex));
  490.      }
  491.      else
  492.      {
  493.         FreeFarMemory( Vertexes);
  494.         Vertexes = NULL;
  495.      }
  496.      for (cur = (*list)->next; cur; cur = cur->next)
  497.         if (cur->objnum > objnum)
  498.            cur->objnum--;
  499.      UnSelectObject( list, objnum);
  500.       }
  501.       break;
  502.    case OBJ_LINEDEFS:
  503.       while (*list)
  504.       {
  505.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  506.      objnum = (*list)->objnum;
  507.      /* delete the two SideDefs bound to this LineDef */
  508.      if (LineDefs[ objnum].sidedef1 >= 0)
  509.      {
  510.         DeleteObject( OBJ_SIDEDEFS, LineDefs[ objnum].sidedef1);
  511.         ObjectsNeeded( OBJ_LINEDEFS, 0);
  512.      }
  513.      if (LineDefs[ objnum].sidedef2 >= 0)
  514.      {
  515.         DeleteObject( OBJ_SIDEDEFS, LineDefs[ objnum].sidedef2);
  516.         ObjectsNeeded( OBJ_LINEDEFS, 0);
  517.      }
  518.      /* delete the LineDef */
  519.      NumLineDefs--;
  520.      if (NumLineDefs > 0)
  521.      {
  522.         for (n = objnum; n < NumLineDefs; n++)
  523.            LineDefs[ n] = LineDefs[ n + 1];
  524.         LineDefs = ResizeFarMemory( LineDefs, NumLineDefs * sizeof( struct LineDef));
  525.      }
  526.      else
  527.      {
  528.         FreeFarMemory( LineDefs);
  529.         LineDefs = NULL;
  530.      }
  531.      for (cur = (*list)->next; cur; cur = cur->next)
  532.         if (cur->objnum > objnum)
  533.            cur->objnum--;
  534.      UnSelectObject( list, objnum);
  535.       }
  536.       break;
  537.    case OBJ_SIDEDEFS:
  538.       while (*list)
  539.       {
  540.      objnum = (*list)->objnum;
  541.      /* change the LineDefs references */
  542.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  543.      for (n = 0; n < NumLineDefs; n++)
  544.      {
  545.         if (LineDefs[ n].sidedef1 == objnum)
  546.            LineDefs[ n].sidedef1 = -1;
  547.         else if (LineDefs[ n].sidedef1 >= objnum)
  548.            LineDefs[ n].sidedef1--;
  549.         if (LineDefs[ n].sidedef2 == objnum)
  550.            LineDefs[ n].sidedef2 = -1;
  551.         else if (LineDefs[ n].sidedef2 >= objnum)
  552.            LineDefs[ n].sidedef2--;
  553.      }
  554.      /* delete the SideDef */
  555.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  556.      NumSideDefs--;
  557.      if (NumSideDefs > 0)
  558.      {
  559.         for (n = objnum; n < NumSideDefs; n++)
  560.            SideDefs[ n] = SideDefs[ n + 1];
  561.         SideDefs = ResizeFarMemory( SideDefs, NumSideDefs * sizeof( struct SideDef));
  562.      }
  563.      else
  564.      {
  565.         FreeFarMemory( SideDefs);
  566.         SideDefs = NULL;
  567.      }
  568.      for (cur = (*list)->next; cur; cur = cur->next)
  569.         if (cur->objnum > objnum)
  570.            cur->objnum--;
  571.      UnSelectObject( list, objnum);
  572.       }
  573.       MadeMapChanges = TRUE;
  574.       break;
  575.    case OBJ_SECTORS:
  576.       while (*list)
  577.       {
  578.      objnum = (*list)->objnum;
  579.      /* delete the SideDefs bound to this Sector and change the references */
  580.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  581.      for (n = 0; n < NumSideDefs; n++)
  582.         if (SideDefs[ n].sector == objnum)
  583.            DeleteObject( OBJ_SIDEDEFS, n--);
  584.         else if (SideDefs[ n].sector >= objnum)
  585.            SideDefs[ n].sector--;
  586.      /* delete the Sector */
  587.      ObjectsNeeded( OBJ_SECTORS, 0);
  588.      NumSectors--;
  589.      if (NumSectors > 0)
  590.      {
  591.         for (n = objnum; n < NumSectors; n++)
  592.            Sectors[ n] = Sectors[ n + 1];
  593.         Sectors = ResizeFarMemory( Sectors, NumSectors * sizeof( struct Sector));
  594.      }
  595.      else
  596.      {
  597.         FreeFarMemory( Sectors);
  598.         Sectors = NULL;
  599.      }
  600.      for (cur = (*list)->next; cur; cur = cur->next)
  601.         if (cur->objnum > objnum)
  602.            cur->objnum--;
  603.      UnSelectObject( list, objnum);
  604.       }
  605.       break;
  606.    default:
  607.       Beep();
  608.    }
  609. }
  610.  
  611.  
  612.  
  613. /*
  614.    insert a new object
  615. */
  616.  
  617. void InsertObject(int objtype, int copyfrom, int xpos, int ypos) /* SWAP! */
  618. {
  619.    int last;
  620.  
  621.    ObjectsNeeded( objtype, 0);
  622.    MadeChanges = TRUE;
  623.    switch (objtype)
  624.    {
  625.    case OBJ_THINGS:
  626.       last = NumThings++;
  627.       if (last > 0)
  628.      Things = ResizeFarMemory( Things, (unsigned long) NumThings * sizeof( struct Thing));
  629.       else
  630.      Things = GetFarMemory( sizeof( struct Thing));
  631.       Things[ last].xpos = xpos;
  632.       Things[ last].ypos = ypos;
  633.       if (copyfrom >= 0)
  634.       {
  635.      Things[ last].type  = Things[ copyfrom].type;
  636.      Things[ last].angle = Things[ copyfrom].angle;
  637.      Things[ last].when  = Things[ copyfrom].when;
  638.       }
  639.       else
  640.       {
  641.      Things[ last].type  = THING_TROOPER;
  642.      Things[ last].angle = 0;
  643.      Things[ last].when  = 0x07;
  644.       }
  645.       break;
  646.    case OBJ_VERTEXES:
  647.       last = NumVertexes++;
  648.       if (last > 0)
  649.      Vertexes = ResizeFarMemory( Vertexes, (unsigned long) NumVertexes * sizeof( struct Vertex));
  650.       else
  651.      Vertexes = GetFarMemory( sizeof( struct Vertex));
  652.       Vertexes[ last].x = xpos & ~7;
  653.       Vertexes[ last].y = ypos & ~7;
  654.       MadeMapChanges = TRUE;
  655.       break;
  656.    case OBJ_LINEDEFS:
  657.       last = NumLineDefs++;
  658.       if (last > 0)
  659.      LineDefs = ResizeFarMemory( LineDefs, (unsigned long) NumLineDefs * sizeof( struct LineDef));
  660.       else
  661.      LineDefs = GetFarMemory( sizeof( struct LineDef));
  662.       if (copyfrom >= 0)
  663.       {
  664.      LineDefs[ last].start = LineDefs[ copyfrom].start;
  665.      LineDefs[ last].end = LineDefs[ copyfrom].end;
  666.      LineDefs[ last].flags = LineDefs[ copyfrom].flags;
  667.      LineDefs[ last].type = LineDefs[ copyfrom].type;
  668.      LineDefs[ last].tag = LineDefs[ copyfrom].tag;
  669.       }
  670.       else
  671.       {
  672.      LineDefs[ last].start = 0;
  673.      LineDefs[ last].end = NumVertexes - 1;
  674.      LineDefs[ last].flags = 1;
  675.      LineDefs[ last].type = 0;
  676.      LineDefs[ last].tag = 0;
  677.       }
  678.       LineDefs[ last].sidedef1 = -1;
  679.       LineDefs[ last].sidedef2 = -1;
  680.       break;
  681.    case OBJ_SIDEDEFS:
  682.       /* SideDefs are added from the LineDefs menu, so "copyfrom" should always be -1.  But I test it anyway. */
  683.       last = NumSideDefs++;
  684.       if (last > 0)
  685.      SideDefs = ResizeFarMemory( SideDefs, (unsigned long) NumSideDefs * sizeof( struct SideDef));
  686.       else
  687.      SideDefs = GetFarMemory( sizeof( struct SideDef));
  688.       if (copyfrom >= 0)
  689.       {
  690.      SideDefs[ last].xoff = SideDefs[ copyfrom].xoff;
  691.      SideDefs[ last].yoff = SideDefs[ copyfrom].yoff;
  692.      strncpy( SideDefs[ last].tex1, SideDefs[ copyfrom].tex1, 8);
  693.      strncpy( SideDefs[ last].tex2, SideDefs[ copyfrom].tex2, 8);
  694.      strncpy( SideDefs[ last].tex3, SideDefs[ copyfrom].tex3, 8);
  695.      SideDefs[ last].sector = SideDefs[ copyfrom].sector;
  696.       }
  697.       else
  698.       {
  699.      SideDefs[ last].xoff = 0;
  700.      SideDefs[ last].yoff = 0;
  701.      strcpy( SideDefs[ last].tex1, "-");
  702.      strcpy( SideDefs[ last].tex2, "-");
  703.      strcpy( SideDefs[ last].tex3, DefaultWallTexture);
  704.      SideDefs[ last].sector = NumSectors - 1;
  705.       }
  706.       MadeMapChanges = TRUE;
  707.       break;
  708.    case OBJ_SECTORS:
  709.       last = NumSectors++;
  710.       if (last > 0)
  711.      Sectors = ResizeFarMemory( Sectors, (unsigned long) NumSectors * sizeof( struct Sector));
  712.       else
  713.      Sectors = GetFarMemory( sizeof( struct Sector));
  714.       if (copyfrom >= 0)
  715.       {
  716.      Sectors[ last].floorh = Sectors[ copyfrom].floorh;
  717.      Sectors[ last].ceilh = Sectors[ copyfrom].ceilh;
  718.      strncpy( Sectors[ last].floort, Sectors[ copyfrom].floort, 8);
  719.      strncpy( Sectors[ last].ceilt, Sectors[ copyfrom].ceilt, 8);
  720.      Sectors[ last].light = Sectors[ copyfrom].light;
  721.      Sectors[ last].special = Sectors[ copyfrom].special;
  722.      Sectors[ last].tag = Sectors[ copyfrom].tag;
  723.       }
  724.       else
  725.       {
  726.      Sectors[ last].floorh = DefaultFloorHeight;
  727.      Sectors[ last].ceilh = DefaultCeilingHeight;
  728.      strncpy( Sectors[ last].floort, DefaultFloorTexture, 8);
  729.      strncpy( Sectors[ last].ceilt, DefaultCeilingTexture, 8);
  730.      Sectors[ last].light = 255;
  731.      Sectors[ last].special = 0;
  732.      Sectors[ last].tag = 0;
  733.       }
  734.       break;
  735.    default:
  736.       Beep();
  737.    }
  738. }
  739.  
  740.  
  741.  
  742. /*
  743.    check if a (part of a) LineDef is inside a given block
  744. */
  745.  
  746. Bool IsLineDefInside( int ldnum, int x0, int y0, int x1, int y1) /* SWAP - needs Vertexes & LineDefs */
  747. {
  748.    int lx0 = Vertexes[ LineDefs[ ldnum].start].x;
  749.    int ly0 = Vertexes[ LineDefs[ ldnum].start].y;
  750.    int lx1 = Vertexes[ LineDefs[ ldnum].end].x;
  751.    int ly1 = Vertexes[ LineDefs[ ldnum].end].y;
  752.    int i;
  753.  
  754.    /* do you like mathematics? */
  755.    if (lx0 >= x0 && lx0 <= x1 && ly0 >= y0 && ly0 <= y1)
  756.       return TRUE; /* the LineDef start is entirely inside the square */
  757.    if (lx1 >= x0 && lx1 <= x1 && ly1 >= y0 && ly1 <= y1)
  758.       return TRUE; /* the LineDef end is entirely inside the square */
  759.    if ((ly0 > y0) != (ly1 > y0))
  760.    {
  761.       i = lx0 + (int) ( (long) (y0 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
  762.       if (i >= x0 && i <= x1)
  763.      return TRUE; /* the LineDef crosses the y0 side (left) */
  764.    }
  765.    if ((ly0 > y1) != (ly1 > y1))
  766.    {
  767.       i = lx0 + (int) ( (long) (y1 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0));
  768.       if (i >= x0 && i <= x1)
  769.      return TRUE; /* the LineDef crosses the y1 side (right) */
  770.    }
  771.    if ((lx0 > x0) != (lx1 > x0))
  772.    {
  773.       i = ly0 + (int) ( (long) (x0 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0));
  774.       if (i >= y0 && i <= y1)
  775.      return TRUE; /* the LineDef crosses the x0 side (down) */
  776.    }
  777.    if ((lx0 > x1) != (lx1 > x1))
  778.    {
  779.       i = ly0 + (int) ( (long) (x1 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0));
  780.       if (i >= y0 && i <= y1)
  781.      return TRUE; /* the LineDef crosses the x1 side (up) */
  782.    }
  783.    return FALSE;
  784. }
  785.  
  786.  
  787.  
  788. /*
  789.    copy a group of objects to a new position
  790. */
  791.  
  792. void CopyObjects( int objtype, SelPtr obj) /* SWAP! */
  793. {
  794.    int        n, m;
  795.    SelPtr     cur;
  796.    SelPtr     list1, list2;
  797.    SelPtr     ref1, ref2;
  798.  
  799.    if (obj == NULL)
  800.       return;
  801.    ObjectsNeeded( objtype, 0);
  802.    /* copy the object(s) */
  803.    switch (objtype)
  804.    {
  805.       case OBJ_THINGS:
  806.      for (cur = obj; cur; cur = cur->next)
  807.      {
  808.         InsertObject( OBJ_THINGS, cur->objnum, Things[ cur->objnum].xpos, Things[ cur->objnum].ypos);
  809.         cur->objnum = NumThings - 1;
  810.      }
  811.      MadeChanges = TRUE;
  812.      break;
  813.  
  814.       case OBJ_VERTEXES:
  815.      for (cur = obj; cur; cur = cur->next)
  816.      {
  817.         InsertObject( OBJ_VERTEXES, cur->objnum, Vertexes[ cur->objnum].x, Vertexes[ cur->objnum].y);
  818.         cur->objnum = NumVertexes - 1;
  819.      }
  820.      MadeChanges = TRUE;
  821.      MadeMapChanges = TRUE;
  822.      break;
  823.  
  824.       case OBJ_LINEDEFS:
  825.      list1 = NULL;
  826.      list2 = NULL;
  827.      /* create the LineDefs */
  828.      for (cur = obj; cur; cur = cur->next)
  829.      {
  830.         InsertObject( OBJ_LINEDEFS, cur->objnum, 0, 0);
  831.         cur->objnum = NumLineDefs - 1;
  832.         if (!IsSelected( list1, LineDefs[ cur->objnum].start))
  833.         {
  834.            SelectObject( &list1, LineDefs[ cur->objnum].start);
  835.            SelectObject( &list2, LineDefs[ cur->objnum].start);
  836.         }
  837.         if (!IsSelected( list1, LineDefs[ cur->objnum].end))
  838.         {
  839.            SelectObject( &list1, LineDefs[ cur->objnum].end);
  840.            SelectObject( &list2, LineDefs[ cur->objnum].end);
  841.         }
  842.      }
  843.      /* create the Vertices */
  844.      CopyObjects( OBJ_VERTEXES, list2);
  845.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  846.      /* update the references to the Vertexes */
  847.      for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
  848.      {
  849.         for (cur = obj; cur; cur = cur->next)
  850.         {
  851.            if (ref1->objnum == LineDefs[ cur->objnum].start)
  852.           LineDefs[ cur->objnum].start = ref2->objnum;
  853.            if (ref1->objnum == LineDefs[ cur->objnum].end)
  854.           LineDefs[ cur->objnum].end = ref2->objnum;
  855.         }
  856.      }
  857.      ForgetSelection( &list1);
  858.      ForgetSelection( &list2);
  859.      break;
  860.  
  861.       case OBJ_SECTORS:
  862.      ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  863.      list1 = NULL;
  864.      list2 = NULL;
  865.      /* create the LineDefs (and Vertices) */
  866.      for (cur = obj; cur; cur = cur->next)
  867.      {
  868.         for (n = 0; n < NumLineDefs; n++)
  869.            if ( (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
  870.           || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
  871.          && ! IsSelected( list1, n))
  872.            {
  873.           SelectObject( &list1, n);
  874.           SelectObject( &list2, n);
  875.            }
  876.      }
  877.      CopyObjects( OBJ_LINEDEFS, list2);
  878.      /* create the SideDefs */
  879.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  880.      for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
  881.      {
  882.         if ((n = LineDefs[ ref1->objnum].sidedef1) >= 0)
  883.         {
  884.            InsertObject( OBJ_SIDEDEFS, n, 0, 0);
  885.            n = NumSideDefs - 1;
  886.            ObjectsNeeded( OBJ_LINEDEFS, 0);
  887.            LineDefs[ ref2->objnum].sidedef1 = n;
  888.         }
  889.         if ((m = LineDefs[ ref1->objnum].sidedef2) >= 0)
  890.         {
  891.            InsertObject( OBJ_SIDEDEFS, m, 0, 0);
  892.            m = NumSideDefs - 1;
  893.            ObjectsNeeded( OBJ_LINEDEFS, 0);
  894.            LineDefs[ ref2->objnum].sidedef2 = m;
  895.         }
  896.         ref1->objnum = n;
  897.         ref2->objnum = m;
  898.      }
  899.      /* create the Sectors */
  900.      for (cur = obj; cur; cur = cur->next)
  901.      {
  902.         InsertObject( OBJ_SECTORS, cur->objnum, 0, 0);
  903.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  904.         for (ref1 = list1, ref2 = list2; ref1 && ref2; ref1 = ref1->next, ref2 = ref2->next)
  905.         {
  906.            if (ref1->objnum >= 0 && SideDefs[ ref1->objnum].sector == cur->objnum)
  907.           SideDefs[ ref1->objnum].sector = NumSectors - 1;
  908.            if (ref2->objnum >= 0 && SideDefs[ ref2->objnum].sector == cur->objnum)
  909.           SideDefs[ ref2->objnum].sector = NumSectors - 1;
  910.         }
  911.         cur->objnum = NumSectors - 1;
  912.      }
  913.      ForgetSelection( &list1);
  914.      ForgetSelection( &list2);
  915.      break;
  916.    }
  917. }
  918.  
  919.  
  920.  
  921. /*
  922.    move a group of objects to a new position
  923.    (must be called with obj = NULL before moving the objects)
  924. */
  925.  
  926. Bool MoveObjectsToCoords( int objtype, SelPtr obj, int newx, int newy, int grid) /* SWAP! */
  927. {
  928.    int        n, m;
  929.    int        dx, dy;
  930.    SelPtr     cur, vertices;
  931.    static int refx, refy;
  932.  
  933.    ObjectsNeeded( objtype, 0);
  934.    if (grid > 0)
  935.    {
  936.       newx = (newx + grid / 2) & ~(grid - 1);
  937.       newy = (newy + grid / 2) & ~(grid - 1);
  938.    }
  939.    else if (objtype == OBJ_VERTEXES)
  940.    {
  941.       newx = (newx + 4) & ~7;
  942.       newy = (newy + 4) & ~7;
  943.    }
  944.  
  945.    /* only update the reference point? */
  946.    if (obj == NULL)
  947.    {
  948.       refx = newx;
  949.       refy = newy;
  950.       return TRUE;
  951.    }
  952.    /* compute the displacement */
  953.    dx = newx - refx;
  954.    dy = newy - refy;
  955.    /* nothing to do? */
  956.    if (dx == 0 && dy == 0)
  957.       return FALSE;
  958.  
  959.    /* move the object(s) */
  960.    switch (objtype)
  961.    {
  962.       case OBJ_THINGS:
  963.      for (cur = obj; cur; cur = cur->next)
  964.      {
  965.         Things[ cur->objnum].xpos += dx;
  966.         Things[ cur->objnum].ypos += dy;
  967.      }
  968.      refx = newx;
  969.      refy = newy;
  970.      MadeChanges = TRUE;
  971.      break;
  972.       case OBJ_VERTEXES:
  973.      for (cur = obj; cur; cur = cur->next)
  974.      {
  975.         Vertexes[ cur->objnum].x += dx;
  976.         Vertexes[ cur->objnum].y += dy;
  977.      }
  978.      refx = newx;
  979.      refy = newy;
  980.      MadeChanges = TRUE;
  981.      MadeMapChanges = TRUE;
  982.      break;
  983.       case OBJ_LINEDEFS:
  984.      vertices = NULL;
  985.      for (cur = obj; cur; cur = cur->next)
  986.      {
  987.         if (!IsSelected( vertices, LineDefs[ cur->objnum].start))
  988.            SelectObject( &vertices, LineDefs[ cur->objnum].start);
  989.         if (!IsSelected( vertices, LineDefs[ cur->objnum].end))
  990.            SelectObject( &vertices, LineDefs[ cur->objnum].end);
  991.      }
  992.      MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
  993.      ForgetSelection( &vertices);
  994.      break;
  995.       case OBJ_SECTORS:
  996.      ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  997.      vertices = NULL;
  998.      for (cur = obj; cur; cur = cur->next)
  999.      {
  1000.         for (n = 0; n < NumLineDefs; n++)
  1001.            if (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
  1002.         || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
  1003.            {
  1004.           if (!IsSelected( vertices, LineDefs[ n].start))
  1005.              SelectObject( &vertices, LineDefs[ n].start);
  1006.           if (!IsSelected( vertices, LineDefs[ n].end))
  1007.              SelectObject( &vertices, LineDefs[ n].end);
  1008.            }
  1009.      }
  1010.      MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
  1011.      ForgetSelection( &vertices);
  1012.      break;
  1013.    }
  1014.    return TRUE;
  1015. }
  1016.  
  1017.  
  1018.  
  1019. /*
  1020.    get the coordinates (approx.) of an object
  1021. */
  1022.  
  1023. void GetObjectCoords( int objtype, int objnum, int *xpos, int *ypos) /* SWAP! */
  1024. {
  1025.    int  n, v1, v2, sd1, sd2;
  1026.    long accx, accy, num;
  1027.  
  1028.    switch (objtype)
  1029.    {
  1030.       case OBJ_THINGS:
  1031.      ObjectsNeeded( OBJ_THINGS, 0);
  1032.      *xpos = Things[ objnum].xpos;
  1033.      *ypos = Things[ objnum].ypos;
  1034.      break;
  1035.       case OBJ_VERTEXES:
  1036.      ObjectsNeeded( OBJ_VERTEXES, 0);
  1037.      *xpos = Vertexes[ objnum].x;
  1038.      *ypos = Vertexes[ objnum].y;
  1039.      break;
  1040.       case OBJ_LINEDEFS:
  1041.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  1042.      v1 = LineDefs[ objnum].start;
  1043.      v2 = LineDefs[ objnum].end;
  1044.      ObjectsNeeded( OBJ_VERTEXES, 0);
  1045.      *xpos = (Vertexes[ v1].x + Vertexes[ v2].x) / 2;
  1046.      *ypos = (Vertexes[ v1].y + Vertexes[ v2].y) / 2;
  1047.      break;
  1048.       case OBJ_SIDEDEFS:
  1049.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  1050.      for (n = 0; n < NumLineDefs; n++)
  1051.         if (LineDefs[ n].sidedef1 == objnum || LineDefs[ n].sidedef2 == objnum)
  1052.         {
  1053.            v1 = LineDefs[ n].start;
  1054.            v2 = LineDefs[ n].end;
  1055.            ObjectsNeeded( OBJ_VERTEXES, 0);
  1056.            *xpos = (Vertexes[ v1].x + Vertexes[ v2].x) / 2;
  1057.            *ypos = (Vertexes[ v1].y + Vertexes[ v2].y) / 2;
  1058.            return;
  1059.         }
  1060.      *xpos = (MapMinX + MapMaxX) / 2;
  1061.      *ypos = (MapMinY + MapMaxY) / 2;
  1062.       case OBJ_SECTORS:
  1063.      accx = 0L;
  1064.      accy = 0L;
  1065.      num = 0L;
  1066.      for (n = 0; n < NumLineDefs; n++)
  1067.      {
  1068.         ObjectsNeeded( OBJ_LINEDEFS, 0);
  1069.         sd1 = LineDefs[ n].sidedef1;
  1070.         sd2 = LineDefs[ n].sidedef2;
  1071.         v1 = LineDefs[ n].start;
  1072.         v2 = LineDefs[ n].end;
  1073.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1074.         if ((sd1 >= 0 && SideDefs[ sd1].sector == objnum) || (sd2 >= 0 && SideDefs[ sd2].sector == objnum))
  1075.         {
  1076.            ObjectsNeeded( OBJ_VERTEXES, 0);
  1077.            /* if the Sector is closed, all Vertices will be counted twice */
  1078.            accx += (long) Vertexes[ v1].x;
  1079.            accy += (long) Vertexes[ v1].y;
  1080.            num++;
  1081.            accx += (long) Vertexes[ v2].x;
  1082.            accy += (long) Vertexes[ v2].y;
  1083.            num++;
  1084.         }
  1085.      }
  1086.      if (num > 0)
  1087.      {
  1088.         *xpos = (int) ((accx + num / 2L) / num);
  1089.         *ypos = (int) ((accy + num / 2L) / num);
  1090.      }
  1091.      else
  1092.      {
  1093.         *xpos = (MapMinX + MapMaxX) / 2;
  1094.         *ypos = (MapMinY + MapMaxY) / 2;
  1095.      }
  1096.      break;
  1097.    }
  1098. }
  1099.  
  1100.  
  1101.  
  1102. /*
  1103.    rotate and scale a group of objects around the center of gravity
  1104. */
  1105.  
  1106. void RotateAndScaleObjects( int objtype, SelPtr obj, double angle, double scale) /* SWAP! */
  1107. {
  1108.    int    n, m;
  1109.    int    dx, dy;
  1110.    int    centerx, centery;
  1111.    long   accx, accy, num;
  1112.    SelPtr cur, vertices;
  1113.  
  1114.    if (obj == NULL)
  1115.       return;
  1116.    ObjectsNeeded( objtype, 0);
  1117.  
  1118.    switch (objtype)
  1119.    {
  1120.       case OBJ_THINGS:
  1121.      accx = 0L;
  1122.      accy = 0L;
  1123.      num = 0L;
  1124.      for (cur = obj; cur; cur = cur->next)
  1125.      {
  1126.         accx += (long) Things[ cur->objnum].xpos;
  1127.         accy += (long) Things[ cur->objnum].ypos;
  1128.         num++;
  1129.      }
  1130.      centerx = (int) ((accx + num / 2L) / num);
  1131.      centery = (int) ((accy + num / 2L) / num);
  1132.      for (cur = obj; cur; cur = cur->next)
  1133.      {
  1134.         dx = Things[ cur->objnum].xpos - centerx;
  1135.         dy = Things[ cur->objnum].ypos - centery;
  1136.         RotateAndScaleCoords( &dx, &dy, angle, scale);
  1137.         Things[ cur->objnum].xpos = centerx + dx;
  1138.         Things[ cur->objnum].ypos = centery + dy;
  1139.      }
  1140.      MadeChanges = TRUE;
  1141.      break;
  1142.       case OBJ_VERTEXES:
  1143.      accx = 0L;
  1144.      accy = 0L;
  1145.      num = 0L;
  1146.      for (cur = obj; cur; cur = cur->next)
  1147.      {
  1148.         accx += (long) Vertexes[ cur->objnum].x;
  1149.         accy += (long) Vertexes[ cur->objnum].y;
  1150.         num++;
  1151.      }
  1152.      centerx = (int) ((accx + num / 2L) / num);
  1153.      centery = (int) ((accy + num / 2L) / num);
  1154.      for (cur = obj; cur; cur = cur->next)
  1155.      {
  1156.         dx = Vertexes[ cur->objnum].x - centerx;
  1157.         dy = Vertexes[ cur->objnum].y - centery;
  1158.         RotateAndScaleCoords( &dx, &dy, angle, scale);
  1159.         Vertexes[ cur->objnum].x = (centerx + dx + 4) & ~7;
  1160.         Vertexes[ cur->objnum].y = (centery + dy + 4) & ~7;
  1161.      }
  1162.      MadeChanges = TRUE;
  1163.      MadeMapChanges = TRUE;
  1164.      break;
  1165.       case OBJ_LINEDEFS:
  1166.      vertices = NULL;
  1167.      for (cur = obj; cur; cur = cur->next)
  1168.      {
  1169.         if (!IsSelected( vertices, LineDefs[ cur->objnum].start))
  1170.            SelectObject( &vertices, LineDefs[ cur->objnum].start);
  1171.         if (!IsSelected( vertices, LineDefs[ cur->objnum].end))
  1172.            SelectObject( &vertices, LineDefs[ cur->objnum].end);
  1173.      }
  1174.      RotateAndScaleObjects( OBJ_VERTEXES, vertices, angle, scale);
  1175.      ForgetSelection( &vertices);
  1176.      break;
  1177.       case OBJ_SECTORS:
  1178.      ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  1179.      vertices = NULL;
  1180.      for (cur = obj; cur; cur = cur->next)
  1181.      {
  1182.         for (n = 0; n < NumLineDefs; n++)
  1183.            if (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
  1184.         || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
  1185.            {
  1186.           if (!IsSelected( vertices, LineDefs[ n].start))
  1187.              SelectObject( &vertices, LineDefs[ n].start);
  1188.           if (!IsSelected( vertices, LineDefs[ n].end))
  1189.              SelectObject( &vertices, LineDefs[ n].end);
  1190.            }
  1191.      }
  1192.      RotateAndScaleObjects( OBJ_VERTEXES, vertices, angle, scale);
  1193.      ForgetSelection( &vertices);
  1194.      break;
  1195.    }
  1196. }
  1197.  
  1198.  
  1199.  
  1200. /*
  1201.    find a free tag number
  1202. */
  1203.  
  1204. int FindFreeTag() /* SWAP! */
  1205. {
  1206.    int  tag, n;
  1207.    Bool ok;
  1208.  
  1209.    ObjectsNeeded( OBJ_LINEDEFS, OBJ_SECTORS, 0);
  1210.    tag = 1;
  1211.    ok = FALSE;
  1212.    while (! ok)
  1213.    {
  1214.       ok = TRUE;
  1215.       for (n = 0; n < NumLineDefs; n++)
  1216.      if (LineDefs[ n].tag == tag)
  1217.      {
  1218.         ok = FALSE;
  1219.         break;
  1220.      }
  1221.       if (ok)
  1222.      for (n = 0; n < NumSectors; n++)
  1223.         if (Sectors[ n].tag == tag)
  1224.         {
  1225.            ok = FALSE;
  1226.            break;
  1227.         }
  1228.       tag++;
  1229.    }
  1230.    return tag - 1;
  1231. }
  1232.  
  1233.  
  1234.  
  1235. /*
  1236.    flip one or several LineDefs
  1237. */
  1238.  
  1239. void FlipLineDefs( SelPtr obj, Bool swapvertices) /* SWAP! */
  1240. {
  1241.    SelPtr cur;
  1242.    int    tmp;
  1243.  
  1244.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1245.    for (cur = obj; cur; cur = cur->next)
  1246.    {
  1247.       if (swapvertices)
  1248.       {
  1249.      /* swap starting and ending Vertices */
  1250.      tmp = LineDefs[ cur->objnum].end;
  1251.      LineDefs[ cur->objnum].end = LineDefs[ cur->objnum].start;
  1252.      LineDefs[ cur->objnum].start = tmp;
  1253.       }
  1254.       /* swap first and second SideDefs */
  1255.       tmp = LineDefs[ cur->objnum].sidedef1;
  1256.       LineDefs[ cur->objnum].sidedef1 = LineDefs[ cur->objnum].sidedef2;
  1257.       LineDefs[ cur->objnum].sidedef2 = tmp;
  1258.    }
  1259.    MadeChanges = TRUE;
  1260.    MadeMapChanges = TRUE;
  1261. }
  1262.  
  1263.  
  1264.  
  1265. /*
  1266.    delete a vertex and join the two linedefs
  1267. */
  1268.  
  1269. void DeleteVerticesJoinLineDefs( SelPtr obj) /* SWAP! */
  1270. {
  1271.    int    lstart, lend, l;
  1272.    SelPtr cur;
  1273.    char   msg[ 80];
  1274.  
  1275.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1276.    while (obj)
  1277.    {
  1278.       cur = obj;
  1279.       obj = obj->next;
  1280.       lstart = -1;
  1281.       lend = -1;
  1282.       for (l = 0; l < NumLineDefs; l++)
  1283.       {
  1284.      if (LineDefs[ l].start == cur->objnum)
  1285.      {
  1286.         if (lstart == -1)
  1287.            lstart = l;
  1288.         else
  1289.            lstart = -2;
  1290.      }
  1291.      if (LineDefs[ l].end == cur->objnum)
  1292.      {
  1293.         if (lend == -1)
  1294.            lend = l;
  1295.         else
  1296.            lend = -2;
  1297.      }
  1298.       }
  1299.       if (lstart < 0 || lend < 0)
  1300.       {
  1301.      Beep();
  1302.      sprintf(msg, "Cannot delete Vertex #%d and join the LineDefs", cur->objnum);
  1303.      Notify( -1, -1, msg, "The Vertex must be the start of one LineDef and the end of another one");
  1304.      continue;
  1305.       }
  1306.       LineDefs[ lend].end = LineDefs[ lstart].end;
  1307.       DeleteObject( OBJ_LINEDEFS, lstart);
  1308.       DeleteObject( OBJ_VERTEXES, cur->objnum);
  1309.       MadeChanges = TRUE;
  1310.       MadeMapChanges = TRUE;
  1311.    }
  1312. }
  1313.  
  1314.  
  1315.  
  1316. /*
  1317.    merge several vertices into one
  1318. */
  1319.  
  1320. void MergeVertices( SelPtr *list) /* SWAP! */
  1321. {
  1322.    int    v, l;
  1323.  
  1324.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1325.    v = (*list)->objnum;
  1326.    UnSelectObject( list, v);
  1327.    if (*list == NULL)
  1328.    {
  1329.       Beep();
  1330.       Notify( -1, -1, "You must select at least two vertices", NULL);
  1331.       return;
  1332.    }
  1333.    /* change the LineDefs starts & ends */
  1334.    for (l = 0; l < NumLineDefs; l++)
  1335.    {
  1336.       if (IsSelected( *list, LineDefs[ l].start))
  1337.       {
  1338.      /* don't change a LineDef that has both ends on the same spot */
  1339.      if (!IsSelected( *list, LineDefs[ l].end) && LineDefs[ l].end != v)
  1340.         LineDefs[ l].start = v;
  1341.       }
  1342.       else if (IsSelected( *list, LineDefs[ l].end))
  1343.       {
  1344.      /* idem */
  1345.      if (LineDefs[ l].start != v)
  1346.         LineDefs[ l].end = v;
  1347.       }
  1348.    }
  1349.    /* delete the Vertices (and some LineDefs too) */
  1350.    DeleteObjects( OBJ_VERTEXES, list);
  1351.    MadeChanges = TRUE;
  1352.    MadeMapChanges = TRUE;
  1353. }
  1354.  
  1355.  
  1356.  
  1357. /*
  1358.    check if some vertices should be merged into one
  1359. */
  1360.  
  1361. Bool CheckMergedVertices( SelPtr *list) /* SWAP! */
  1362. {
  1363.    SelPtr ref, cur;
  1364.    Bool   confirmed, redraw;
  1365.    int    v, refv;
  1366.  
  1367.    ObjectsNeeded( OBJ_VERTEXES, 0);
  1368.    confirmed = FALSE;
  1369.    redraw = FALSE;
  1370.    ref = *list;
  1371.    while (ref)
  1372.    {
  1373.       refv = ref->objnum;
  1374.       ref = ref->next;
  1375.       /* check if there is a Vertex at the same position (same X and Y) */
  1376.       for (v = 0; v < NumVertexes; v++)
  1377.      if (v != refv && Vertexes[ refv].x == Vertexes[ v].x && Vertexes[ refv].y == Vertexes[ v].y)
  1378.      {
  1379.         redraw = TRUE;
  1380.         if (confirmed || Expert || Confirm( -1, -1, "Some Vertices occupy the same position", "Do you want to merge them into one?"))
  1381.         {
  1382.            /* don't ask for confirmation twice */
  1383.            confirmed = TRUE;
  1384.            /* merge the two vertices */
  1385.            cur = NULL;
  1386.            SelectObject( &cur, refv);
  1387.            SelectObject( &cur, v);
  1388.            MergeVertices( &cur);
  1389.            /* not useful but safer... */
  1390.            ObjectsNeeded( OBJ_VERTEXES, 0);
  1391.            /* update the references in the selection list */
  1392.            for (cur = *list; cur; cur = cur->next)
  1393.           if (cur->objnum > refv)
  1394.              cur->objnum = cur->objnum - 1;
  1395.            if (v > refv)
  1396.           v--;
  1397.            /* the old Vertex has been deleted */
  1398.            UnSelectObject( list, refv);
  1399.            /* select the new Vertex instead */
  1400.            if (!IsSelected( *list, v))
  1401.           SelectObject( list, v);
  1402.            break;
  1403.         }
  1404.         else
  1405.            return redraw;
  1406.      }
  1407.    }
  1408.    return redraw;
  1409. }
  1410.  
  1411.  
  1412.  
  1413. /*
  1414.    split one or more LineDefs in two, adding new Vertices in the middle
  1415. */
  1416.  
  1417. void SplitLineDefs( SelPtr obj) /* SWAP! */
  1418. {
  1419.    SelPtr cur;
  1420.    int    vstart, vend, sd;
  1421.  
  1422.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1423.    for (cur = obj; cur; cur = cur->next)
  1424.    {
  1425.       vstart = LineDefs[ cur->objnum].start;
  1426.       vend = LineDefs[ cur->objnum].end;
  1427.       InsertObject( OBJ_VERTEXES, -1, (Vertexes[ vstart].x + Vertexes[ vend].x) / 2, (Vertexes[ vstart].y + Vertexes[ vend].y) / 2);
  1428.       InsertObject( OBJ_LINEDEFS, cur->objnum, 0, 0);
  1429.       LineDefs[ cur->objnum].end = NumVertexes - 1;
  1430.       LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  1431.       sd = LineDefs[ cur->objnum].sidedef1;
  1432.       if (sd >= 0)
  1433.       {
  1434.      InsertObject( OBJ_SIDEDEFS, sd, 0, 0);
  1435.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  1436.      LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
  1437.       }
  1438.       sd = LineDefs[ cur->objnum].sidedef2;
  1439.       if (sd >= 0)
  1440.       {
  1441.      InsertObject( OBJ_SIDEDEFS, sd, 0, 0);
  1442.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  1443.      LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
  1444.       }
  1445.    }
  1446.    MadeChanges = TRUE;
  1447.    MadeMapChanges = TRUE;
  1448. }
  1449.  
  1450.  
  1451.  
  1452. /*
  1453.    split a Sector in two, adding a new LineDef between the two Vertices
  1454. */
  1455.  
  1456. void SplitSector( int vertex1, int vertex2) /* SWAP! */
  1457. {
  1458.    SelPtr llist;
  1459.    int    curv, s, l, sd;
  1460.    char   msg1[ 80], msg2[ 80];
  1461.  
  1462.    /* check if there is a Sector between the two Vertices (in the middle) */
  1463.    s = GetCurObject( OBJ_SECTORS, Vertexes[ vertex1].x, Vertexes[ vertex1].y, Vertexes[ vertex2].x, Vertexes[ vertex2].y);
  1464.    if (s < 0)
  1465.    {
  1466.       Beep();
  1467.       sprintf( msg1, "There is no Sector between Vertex #%d and Vertex #%d", vertex1, vertex2);
  1468.       Notify( -1, -1, msg1, NULL);
  1469.       return;
  1470.    }
  1471.    /* check if there is a closed path from vertex1 to vertex2, along the edge of the Sector s */
  1472.    ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  1473.    llist = NULL;
  1474.    curv = vertex1;
  1475.    while (curv != vertex2)
  1476.    {
  1477.       for (l = 0; l < NumLineDefs; l++)
  1478.       {
  1479.      sd = LineDefs[ l].sidedef1;
  1480.      if (sd >= 0 && SideDefs[ sd].sector == s && LineDefs[ l].start == curv)
  1481.      {
  1482.         curv = LineDefs[ l].end;
  1483.         SelectObject( &llist, l);
  1484.         break;
  1485.      }
  1486.      sd = LineDefs[ l].sidedef2;
  1487.      if (sd >= 0 && SideDefs[ sd].sector == s && LineDefs[ l].end == curv)
  1488.      {
  1489.         curv = LineDefs[ l].start;
  1490.         SelectObject( &llist, l);
  1491.         break;
  1492.      }
  1493.       }
  1494.       if (l >= NumLineDefs)
  1495.       {
  1496.      Beep();
  1497.      sprintf( msg1, "Cannot find a closed path from Vertex #%d to Vertex #%d", vertex1, vertex2);
  1498.      if (curv == vertex1)
  1499.         sprintf( msg2, "There is no SideDef starting from Vertex #%d on Sector #%d", vertex1, s);
  1500.      else
  1501.         sprintf( msg2, "Check if Sector #%d is closed (cannot go past Vertex #%d)", s, curv);
  1502.      Notify( -1, -1, msg1, msg2);
  1503.      ForgetSelection( &llist);
  1504.      return;
  1505.       }
  1506.       if (curv == vertex1)
  1507.       {
  1508.      Beep();
  1509.      sprintf( msg1, "Vertex #%d is not on the same Sector (#%d) as Vertex #%d", vertex2, s, vertex1);
  1510.      Notify( -1, -1, msg1, NULL);
  1511.      ForgetSelection( &llist);
  1512.      return;
  1513.       }
  1514.    }
  1515.    /* now, the list of LineDefs for the new Sector is in llist */
  1516.  
  1517.    /* add the new Sector, LineDef and SideDefs */
  1518.    InsertObject( OBJ_SECTORS, s, 0, 0);
  1519.    InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  1520.    LineDefs[ NumLineDefs - 1].start = vertex1;
  1521.    LineDefs[ NumLineDefs - 1].end = vertex2;
  1522.    LineDefs[ NumLineDefs - 1].flags = 4;
  1523.    InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1524.    SideDefs[ NumSideDefs - 1].sector = s;
  1525.    strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
  1526.    InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1527.    strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
  1528.    ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  1529.    LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 2;
  1530.    LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
  1531.    /* bind all LineDefs in llist to the new Sector */
  1532.    while (llist)
  1533.    {
  1534.       sd = LineDefs[ llist->objnum].sidedef1;
  1535.       if (sd < 0 || SideDefs[ sd].sector != s)
  1536.      sd = LineDefs[ llist->objnum].sidedef2;
  1537.       SideDefs[ sd].sector = NumSectors - 1;
  1538.       UnSelectObject( &llist, llist->objnum);
  1539.    }
  1540.    MadeChanges = TRUE;
  1541.    MadeMapChanges = TRUE;
  1542. }
  1543.  
  1544.  
  1545.  
  1546. /*
  1547.    split two LineDefs, then split the Sector and add a new LineDef between the new Vertices
  1548. */
  1549.  
  1550. void SplitLineDefsAndSector( int linedef1, int linedef2) /* SWAP! */
  1551. {
  1552.    SelPtr llist;
  1553.    int    s1, s2, s3, s4;
  1554.    char   msg[ 80];
  1555.  
  1556.    /* check if the two LineDefs are adjacent to the same Sector */
  1557.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1558.    s1 = LineDefs[ linedef1].sidedef1;
  1559.    s2 = LineDefs[ linedef1].sidedef2;
  1560.    s3 = LineDefs[ linedef2].sidedef1;
  1561.    s4 = LineDefs[ linedef2].sidedef2;
  1562.    ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1563.    if (s1 >= 0)
  1564.       s1 = SideDefs[ s1].sector;
  1565.    if (s2 >= 0)
  1566.       s2 = SideDefs[ s2].sector;
  1567.    if (s3 >= 0)
  1568.       s3 = SideDefs[ s3].sector;
  1569.    if (s4 >= 0)
  1570.       s4 = SideDefs[ s4].sector;
  1571.    if ((s1 < 0 || (s1 != s3 && s1 != s4)) && (s2 < 0 || (s2 != s3 && s2 != s4)))
  1572.    {
  1573.       Beep();
  1574.       sprintf( msg, "LineDefs #%d and #%d are not adjacent to the same Sector", linedef1, linedef2);
  1575.       Notify( -1, -1, msg, NULL);
  1576.       return;
  1577.    }
  1578.    /* split the two LineDefs and create two new Vertices */
  1579.    llist = NULL;
  1580.    SelectObject( &llist, linedef1);
  1581.    SelectObject( &llist, linedef2);
  1582.    SplitLineDefs( llist);
  1583.    ForgetSelection( &llist);
  1584.    /* split the Sector and create a LineDef between the two Vertices */
  1585.    SplitSector( NumVertexes - 1, NumVertexes - 2);
  1586. }
  1587.  
  1588.  
  1589.  
  1590. /*
  1591.    turn a Sector into a door: change the LineDefs and SideDefs
  1592. */
  1593.  
  1594. void MakeDoorFromSector( int sector) /* SWAP! */
  1595. {
  1596.    int    sd1, sd2;
  1597.    int    n, s;
  1598.    SelPtr ldok, ldflip, ld1s;
  1599.  
  1600.    ldok = NULL;
  1601.    ldflip = NULL;
  1602.    ld1s = NULL;
  1603.    s = 0;
  1604.    /* build lists of LineDefs that border the Sector */
  1605.    for (n = 0; n < NumLineDefs; n++)
  1606.    {
  1607.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1608.       sd1 = LineDefs[ n].sidedef1;
  1609.       sd2 = LineDefs[ n].sidedef2;
  1610.       if (sd1 >= 0 && sd2 >= 0)
  1611.       {
  1612.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1613.      if (SideDefs[ sd2].sector == sector)
  1614.      {
  1615.         SelectObject( &ldok, n); /* already ok */
  1616.         s++;
  1617.      }
  1618.      if (SideDefs[ sd1].sector == sector)
  1619.      {
  1620.         SelectObject( &ldflip, n); /* must be flipped */
  1621.         s++;
  1622.      }
  1623.       }
  1624.       else if (sd1 >= 0 && sd2 < 0)
  1625.       {
  1626.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1627.      if (SideDefs[ sd1].sector == sector)
  1628.         SelectObject( &ld1s, n); /* wall (one-sided) */
  1629.       }
  1630.    }
  1631.    /* a normal door has two sides... */
  1632.    if (s < 2)
  1633.    {
  1634.       Beep();
  1635.       Notify( -1, -1, "The door must be connected to two other Sectors.", NULL);
  1636.       ForgetSelection( &ldok);
  1637.       ForgetSelection( &ldflip);
  1638.       ForgetSelection( &ld1s);
  1639.       return;
  1640.    }
  1641.    if ((s > 2) && !(Expert || Confirm( -1, -1, "The door will have more than two sides.", "Do you still want to create it?")))
  1642.    {
  1643.       ForgetSelection( &ldok);
  1644.       ForgetSelection( &ldflip);
  1645.       ForgetSelection( &ld1s);
  1646.       return;
  1647.    }
  1648.    /* flip the LineDefs that have the wrong orientation */
  1649.    if (ldflip != NULL)
  1650.       FlipLineDefs( ldflip, TRUE);
  1651.    /* merge the two selection lists */
  1652.    while (ldflip != NULL)
  1653.    {
  1654.       if (!IsSelected( ldok, ldflip->objnum))
  1655.      SelectObject( &ldok, ldflip->objnum);
  1656.       UnSelectObject( &ldflip, ldflip->objnum);
  1657.    }
  1658.    /* change the LineDefs and SideDefs */
  1659.    while (ldok != NULL)
  1660.    {
  1661.       /* give the "normal door" type and flags to the LineDef */
  1662.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1663.       n = ldok->objnum;
  1664.       LineDefs[ n].type = 1;
  1665.       LineDefs[ n].flags = 0x04;
  1666.       sd1 = LineDefs[ n].sidedef1;
  1667.       sd2 = LineDefs[ n].sidedef2;
  1668.       /* adjust the textures for the SideDefs */
  1669.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1670.       if (strncmp( SideDefs[ sd1].tex3, "-", 8))
  1671.       {
  1672.      if (!strncmp( SideDefs[ sd1].tex1, "-", 8))
  1673.         strncpy( SideDefs[ sd1].tex1, SideDefs[ sd1].tex3, 8);
  1674.      strncpy( SideDefs[ sd1].tex3, "-", 8);
  1675.       }
  1676.       if (!strncmp( SideDefs[ sd1].tex1, "-", 8))
  1677.      strncpy( SideDefs[ sd1].tex1, "BIGDOOR2", 8);
  1678.       strncpy( SideDefs[ sd2].tex3, "-", 8);
  1679.       UnSelectObject( &ldok, n);
  1680.    }
  1681.    while (ld1s != NULL)
  1682.    {
  1683.       /* give the "door side" flags to the LineDef */
  1684.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1685.       n = ld1s->objnum;
  1686.       LineDefs[ n].flags = 0x11;
  1687.       sd1 = LineDefs[ n].sidedef1;
  1688.       /* adjust the textures for the SideDef */
  1689.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1690.       if (!strncmp( SideDefs[ sd1].tex3, "-", 8))
  1691.      strncpy( SideDefs[ sd1].tex3, "DOORTRAK", 8);
  1692.       strncpy( SideDefs[ sd1].tex1, "-", 8);
  1693.       strncpy( SideDefs[ sd1].tex2, "-", 8);
  1694.       UnSelectObject( &ld1s, n);
  1695.    }
  1696.    /* adjust the ceiling height */
  1697.    ObjectsNeeded( OBJ_SECTORS, 0);
  1698.    Sectors[ sector].ceilh = Sectors[ sector].floorh;
  1699. }
  1700.  
  1701.  
  1702.  
  1703. /*
  1704.    turn a Sector into a lift: change the LineDefs and SideDefs
  1705. */
  1706.  
  1707. void MakeLiftFromSector( int sector) /* SWAP! */
  1708. {
  1709.    int    sd1, sd2;
  1710.    int    n, s, tag;
  1711.    SelPtr ldok, ldflip, ld1s;
  1712.    SelPtr sect, curs;
  1713.    int    minh, maxh;
  1714.  
  1715.    ldok = NULL;
  1716.    ldflip = NULL;
  1717.    ld1s = NULL;
  1718.    sect = NULL;
  1719.    /* build lists of LineDefs that border the Sector */
  1720.    for (n = 0; n < NumLineDefs; n++)
  1721.    {
  1722.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1723.       sd1 = LineDefs[ n].sidedef1;
  1724.       sd2 = LineDefs[ n].sidedef2;
  1725.       if (sd1 >= 0 && sd2 >= 0)
  1726.       {
  1727.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1728.      if (SideDefs[ sd2].sector == sector)
  1729.      {
  1730.         SelectObject( &ldok, n); /* already ok */
  1731.         s = SideDefs[ sd1].sector;
  1732.         if (s != sector && !IsSelected( sect, s))
  1733.            SelectObject( §, s);
  1734.      }
  1735.      if (SideDefs[ sd1].sector == sector)
  1736.      {
  1737.         SelectObject( &ldflip, n); /* will be flipped */
  1738.         s = SideDefs[ sd2].sector;
  1739.         if (s != sector && !IsSelected( sect, s))
  1740.            SelectObject( §, s);
  1741.      }
  1742.       }
  1743.       else if (sd1 >= 0 && sd2 < 0)
  1744.       {
  1745.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1746.      if (SideDefs[ sd1].sector == sector)
  1747.         SelectObject( &ld1s, n); /* wall (one-sided) */
  1748.       }
  1749.    }
  1750.    /* there must be a way to go on the lift... */
  1751.    if (sect == NULL)
  1752.    {
  1753.       Beep();
  1754.       Notify( -1, -1, "The lift must be connected to at least one other Sector.", NULL);
  1755.       ForgetSelection( &ldok);
  1756.       ForgetSelection( &ldflip);
  1757.       ForgetSelection( &ld1s);
  1758.       return;
  1759.    }
  1760.    /* flip the LineDefs that have the wrong orientation */
  1761.    if (ldflip != NULL)
  1762.       FlipLineDefs( ldflip, TRUE);
  1763.    /* merge the two selection lists */
  1764.    while (ldflip != NULL)
  1765.    {
  1766.       if (!IsSelected( ldok, ldflip->objnum))
  1767.      SelectObject( &ldok, ldflip->objnum);
  1768.       UnSelectObject( &ldflip, ldflip->objnum);
  1769.    }
  1770.    /* find a free tag number */
  1771.    tag = FindFreeTag();
  1772.    /* find the minimum altitude */
  1773.    ObjectsNeeded( OBJ_SECTORS, 0);
  1774.    minh = 32767;
  1775.    maxh = -32768;
  1776.    for (curs = sect; curs; curs = curs->next)
  1777.    {
  1778.       if (Sectors[ curs->objnum].floorh < minh)
  1779.      minh = Sectors[ curs->objnum].floorh;
  1780.       if (Sectors[ curs->objnum].floorh > maxh)
  1781.      maxh = Sectors[ curs->objnum].floorh;
  1782.    }
  1783.    ForgetSelection( §);
  1784.    /* change the Sector altitude if necessary */
  1785.    if (Sectors[ sector].floorh < maxh)
  1786.       Sectors[ sector].floorh = maxh;
  1787.    Sectors[ sector].tag = tag;
  1788.    /* change the LineDefs and SideDefs */
  1789.    while (ldok != NULL)
  1790.    {
  1791.       /* give the "lower lift" or "raise lift" type and flags to the LineDef */
  1792.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1793.       n = ldok->objnum;
  1794.       LineDefs[ n].type = 62; /* raise lift & switch for lower */
  1795.       LineDefs[ n].flags = 0x04;
  1796.       LineDefs[ n].tag = tag;
  1797.       sd1 = LineDefs[ n].sidedef1;
  1798.       sd2 = LineDefs[ n].sidedef2;
  1799.       /* adjust the textures for the SideDefs */
  1800.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1801.       if (strncmp( SideDefs[ sd1].tex3, "-", 8))
  1802.       {
  1803.      if (!strncmp( SideDefs[ sd1].tex2, "-", 8))
  1804.         strncpy( SideDefs[ sd1].tex2, SideDefs[ sd1].tex3, 8);
  1805.      strncpy( SideDefs[ sd1].tex3, "-", 8);
  1806.       }
  1807.       if (!strncmp( SideDefs[ sd1].tex2, "-", 8))
  1808.      strncpy( SideDefs[ sd1].tex2, "SHAWN2", 8);
  1809.       strncpy( SideDefs[ sd2].tex3, "-", 8);
  1810.       s = SideDefs[ sd1].sector;
  1811.       ObjectsNeeded( OBJ_SECTORS, 0);
  1812.       if (Sectors[ s].floorh > minh)
  1813.       {
  1814.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1815.      if (strncmp( SideDefs[ sd2].tex3, "-", 8))
  1816.      {
  1817.         if (!strncmp( SideDefs[ sd2].tex2, "-", 8))
  1818.            strncpy( SideDefs[ sd2].tex2, SideDefs[ sd1].tex3, 8);
  1819.         strncpy( SideDefs[ sd2].tex3, "-", 8);
  1820.      }
  1821.      if (!strncmp( SideDefs[ sd2].tex2, "-", 8))
  1822.         strncpy( SideDefs[ sd2].tex2, "SHAWN2", 8);
  1823.       }
  1824.       else
  1825.       {
  1826.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1827.      strncpy( SideDefs[ sd2].tex2, "-", 8);
  1828.       }
  1829.       strncpy( SideDefs[ sd2].tex3, "-", 8);
  1830.       ObjectsNeeded( OBJ_SECTORS, 0);
  1831.       /* if the Sector is above the lift */
  1832.       if (Sectors[ s].floorh >= Sectors[ sector].floorh)
  1833.       {
  1834.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  1835.      LineDefs[ n].type = 88; /* lower lift */
  1836.      /* flip it, just for fun */
  1837.      curs = NULL;
  1838.      SelectObject( &curs, n);
  1839.      FlipLineDefs( curs, TRUE);
  1840.      ForgetSelection( &curs);
  1841.       }
  1842.       UnSelectObject( &ldok, n);
  1843.    }
  1844.    while (ld1s != NULL)
  1845.    {
  1846.       /* these are the lift walls (one-sided) */
  1847.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1848.       n = ld1s->objnum;
  1849.       LineDefs[ n].flags = 0x01;
  1850.       sd1 = LineDefs[ n].sidedef1;
  1851.       /* adjust the textures for the SideDef */
  1852.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1853.       if (!strncmp( SideDefs[ sd1].tex3, "-", 8))
  1854.      strncpy( SideDefs[ sd1].tex3, DefaultWallTexture, 8);
  1855.       strncpy( SideDefs[ sd1].tex1, "-", 8);
  1856.       strncpy( SideDefs[ sd1].tex2, "-", 8);
  1857.       UnSelectObject( &ld1s, n);
  1858.    }
  1859. }
  1860.  
  1861.  
  1862.  
  1863. /*
  1864.    get the absolute height from which the textures are drawn
  1865. */
  1866.  
  1867. int GetTextureRefHeight( int sidedef) /* SWAP! */
  1868. {
  1869.    int l, sector;
  1870.    int otherside;
  1871.  
  1872.    /* find the SideDef on the other side of the LineDef, if any */
  1873.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1874.    for (l = 0; l < NumLineDefs; l++)
  1875.    {
  1876.       if (LineDefs[ l].sidedef1 == sidedef)
  1877.       {
  1878.      otherside = LineDefs[ l].sidedef2;
  1879.      break;
  1880.       }
  1881.       if (LineDefs[ l].sidedef2 == sidedef)
  1882.       {
  1883.      otherside = LineDefs[ l].sidedef1;
  1884.      break;
  1885.       }
  1886.    }
  1887.    /* get the Sector number */
  1888.    ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1889.    sector = SideDefs[ sidedef].sector;
  1890.    /* if the upper texture is displayed, then the reference is taken from the other Sector */
  1891.    if (otherside >= 0)
  1892.    {
  1893.       l = SideDefs[ otherside].sector;
  1894.       if (l > 0)
  1895.       {
  1896.      ObjectsNeeded( OBJ_SECTORS, 0);
  1897.      if (Sectors[ l].ceilh < Sectors[ sector].ceilh && Sectors[ l].ceilh > Sectors[ sector].floorh)
  1898.         sector = l;
  1899.       }
  1900.    }
  1901.    /* return the altitude of the ceiling */
  1902.    ObjectsNeeded( OBJ_SECTORS, 0);
  1903.    if (sector >= 0)
  1904.       return Sectors[ sector].ceilh; /* textures are drawn from the ceiling down */
  1905.    else
  1906.       return 0; /* yuck! */
  1907. }
  1908.  
  1909.  
  1910.  
  1911. /*
  1912.    Align all textures for the given SideDefs
  1913. */
  1914.  
  1915. void AlignTextures( SelPtr *sdlist) /* SWAP! */
  1916. {
  1917.    int h, refh;
  1918.  
  1919.    if (*sdlist == NULL)
  1920.       return;
  1921.    /* get the reference height */
  1922.    refh = GetTextureRefHeight( (*sdlist)->objnum);
  1923.    ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1924.    SideDefs[ (*sdlist)->objnum].yoff = 0;
  1925.    UnSelectObject( sdlist, (*sdlist)->objnum);
  1926.    /* adjust Y offset in all other SideDefs */
  1927.    while (*sdlist != NULL)
  1928.    {
  1929.       h = GetTextureRefHeight( (*sdlist)->objnum);
  1930.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1931.       SideDefs[ (*sdlist)->objnum].yoff = (refh - h) % 128;
  1932.       UnSelectObject( sdlist, (*sdlist)->objnum);
  1933.    }
  1934.    MadeChanges = TRUE;
  1935. }
  1936.  
  1937.  
  1938.  
  1939. /* end of file */
  1940.