home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / qube / gfx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-07  |  20.5 KB  |  788 lines

  1. /***
  2. ****  QuBE --- Graphical display of the level, if possible.
  3. ****
  4. ****  As usual, it still needs work; better support of, well, everyentity.
  5. ***/
  6.  
  7. #include "qube.h"
  8. #include "entities.h"
  9. #include "gfx.h"
  10.  
  11. #ifdef QUBE_MSDOS
  12. #include "svgagfx.h"
  13. #endif
  14. #ifdef QUBE_UNIX
  15. #include "xgfx.h"
  16. #endif
  17.  
  18. static void DrawScrn(int blackify);
  19. static void DrawScrnXOR(int blackify);
  20. static void DrawScrnMove(void);
  21. static void DrawOneEnt(int highlight, int entity);
  22. static void MouseMove(void);
  23. static void ReadEntList(void);
  24. static void ReadVertices(void);
  25. static void ReadEdgeList(void);
  26. static void UpdateEntXOR(int i, int blackify);
  27. static void UpdateEnt(int i, int blackify);
  28. static void EditObject(void);
  29. static void StatusUpdate(void);
  30. static void UpdateEdge(int i, int blackify);
  31. static void UpdateEdgeXOR(int i, int blackify);
  32. static void UpdateVertex(int i, int blackify);
  33. static void UpdateVertexXOR(int i, int blackify);
  34.  
  35. char WaitEvent(void);
  36. int EventsPending(void);
  37.  
  38. static long int orgx = 0, orgy = 0;
  39. static int scale = 4;
  40. static long int deltax, deltay, deltascale;
  41.  
  42. static long int grid = 8;
  43.  
  44. static int omx, omy, omb, tbx = 0, tby = 0;
  45.  
  46. static int NeedUpdate = 0;
  47.  
  48. static char *filename;
  49.  
  50. static float *vlistx;
  51. static float *vlisty;
  52. static float *vlistz;
  53.  
  54. static unsigned int *edgestart;
  55. static unsigned int *edgeend;
  56.  
  57. static long int edgecount;
  58. static long int vertexcount;
  59.  
  60. static mouseready = 0;
  61.  
  62. void DoGraphics(int argnum, char **argv)
  63. {
  64.     entity *tt;
  65.     long int i;
  66.         char c;
  67.         char *type;
  68.     char *entry;
  69.     int x, y;
  70.  
  71.     filename = argv[filenamearg];
  72.  
  73.     ReadEntList();
  74.     ReadVertices();
  75.     ReadEdgeList();
  76.  
  77.     InitScrn(M640x480x256);
  78.     StatusUpdate();
  79.         InitMouse(640, 480, 1, 1);
  80.     mouseready = 1;
  81.         StdCursor(CURarrow);
  82.     MouseOn();
  83.  
  84.         DrawScrnXOR(0);
  85.  
  86.     omx = MouseX;
  87.     omy = MouseY;
  88.     omb = MouseButton();
  89.  
  90.     deltax = deltay = deltascale = 0;
  91.  
  92.     do {
  93.         if (!EventsPending() && NeedUpdate) {
  94.             if (NeedUpdate & 2) DrawScrnMove();
  95.             else DrawScrnXOR(0);
  96.             MouseOn();
  97.             NeedUpdate = 0;
  98.                 }
  99.  
  100.                 switch (c = WaitEvent()) {
  101.         case 0x7F:                /* Refresh Screen */
  102.             NeedUpdate |= 1;
  103.             break;
  104.         case 0x7E:                /* Mouse move */
  105.             for (i = 0; i < nextentity; i++) {
  106.                 if (i != curentity && entityarray[i]->origin != NULL) {
  107.                     x = 320 + (((entityarray[i]->x + orgx) * scale) >> 5);
  108.                     y = 240 - (((entityarray[i]->y + orgy) * scale) >> 5);
  109.                     if (omx > x-4 && omy > y-4 && omx < x+4 && omy < y+4) {
  110.                         DrawOneEnt(0, curentity);
  111.                         DrawOneEnt(1, curentity = i);
  112.                         break;
  113.                     }
  114.                 }
  115.             }
  116.                         break;
  117.         case 0x7D:                /* Mouse button 1 press */
  118.  
  119. /* This is commented out because it's not done yet.  Sorry. */
  120. #if 0
  121.                         if (entityarray[curentity]->origin != NULL) {
  122.                 x = 320 + (((entityarray[curentity]->x + orgx) * scale) >> 5);
  123.                 y = 240 - (((entityarray[curentity]->y + orgy) * scale) >> 5);
  124.                 if (omx > x-4 && omy > y-4 && omx < x+4 && omy < y+4) {
  125.                     char originstr[128];
  126.                     MouseOff();
  127.                     while ((c = WaitEvent()) != 0x7C) {
  128.                         switch (c) {
  129.                         case 0x7F:
  130.                             DrawScrn(1);
  131.                             DrawScrnXOR(0);
  132.                             MouseOn();
  133.                             break;
  134.                                                 case 0x7E:
  135.                             UpdateEntXOR(curentity, -1);
  136.                             entityarray[curentity]->x = (((omx - 320) * 32) / scale) - orgx;
  137.                             entityarray[curentity]->y = (((240 - omy) * 32) / scale) - orgy;
  138.                             UpdateEntXOR(curentity, -1);
  139.                             break;
  140.                         }
  141.                     }
  142.                     DrawOneEnt(0, curentity);
  143.                     DrawOneEnt(1, curentity);
  144.                     MouseOn();
  145.                     Qfree(entityarray[curentity]->origin);
  146.                     sprintf(originstr, "%ld %ld %ld", entityarray[curentity]->x,
  147.                         entityarray[curentity]->y, entityarray[curentity]->z);
  148.                     entityarray[curentity]->origin = Qmalloc(strlen(originstr)+1);
  149.                     strcpy(entityarray[curentity]->origin, originstr);
  150.                 }
  151.             }
  152. #endif
  153.                         if ((omx > tbx && omy > tby+410 && omx < tbx+14 && omy < tby+479) ||
  154.                 (omx > tbx+307 && omy > tby+410 && omx < tbx+320 && omy < tby+479)) {
  155.                                 int ox = omx-tbx, oy = omy-tby;
  156.                 int mx = omx, my = omy;
  157.                                 MouseOff();
  158.                 DrawScrnXOR(0);
  159.                 MouseOff();
  160.                                 BoxOutlnXOR(omx-ox, omy-oy+410, omx-ox+320, omy-oy+479, WHITE);
  161.                                 while ((c = WaitEvent()) != 0x7C) {
  162.                     switch (c) {
  163.                     case 0x7F:
  164.                         DrawScrn(1);
  165.                         DrawScrnXOR(0);
  166.                         break;
  167.                                         case 0x7E:
  168.                         BoxOutlnXOR(mx-ox, my-oy+410, mx-ox+320, my-oy+479, WHITE);
  169.                                                 mx = omx;
  170.                         my = omy;
  171.                         BoxOutlnXOR(omx-ox, omy-oy+410, omx-ox+320, omy-oy+479, WHITE);
  172.                                                 break;
  173.                     }
  174.                 }
  175.                 BoxOutlnXOR(omx-ox, omy-oy+410, omx-ox+320, omy-oy+479, WHITE);
  176.                 BoxFill(tbx, tby+410, tbx+320, tby+479, BLACK);
  177.                 tbx = omx-ox;
  178.                 tby = omy-oy;
  179.                 NeedUpdate |= 1;
  180.                                 MouseOn();
  181.                         }
  182.                         break;
  183.         case 0x7C:                /* Mouse button 1 release */
  184.             break;
  185.         case 0x7B:                /* Mouse button 2 press */
  186.             break;
  187.         case 0x7A:                /* Mouse button 2 release */
  188.             break;
  189.         case 0x1C:                /* Enter/edit key */
  190.             EditObject();
  191.             break;
  192.                 case 0x48:                              /* Up arrow */
  193.             deltay -= (10 * 32) / scale;
  194.             NeedUpdate |= 2;
  195.                         break;
  196.         case 0x4B:                /* Left arrow */
  197.             deltax += (10 * 32) / scale;
  198.             NeedUpdate |= 2;
  199.             break;
  200.         case 0x4D:                /* Right arrow */
  201.             deltax -= (10 * 32) / scale;
  202.             NeedUpdate |= 2;
  203.             break;
  204.         case 0x50:                /* Down arrow */
  205.             deltay += (10 * 32) / scale;
  206.             NeedUpdate |= 2;
  207.             break;
  208.         case 0xC:                /* Minus/zoom out */
  209.             if (scale+deltascale > 1) {
  210.                 deltascale--;
  211.                 NeedUpdate |= 2;
  212.             }
  213.             break;
  214.         case 0xD:                /* Plus/zoom in */
  215.             if (scale+deltascale < 32) {
  216.                 deltascale++;
  217.                 NeedUpdate |= 2;
  218.             }
  219.             break;
  220.         case 0x31:                /* N/next object */
  221.             DrawOneEnt(0, curentity);
  222.             do {
  223.                 if (++curentity >= nextentity) curentity = 0;
  224.             } while (entityarray[curentity]->type == ENTITY_LIGHT);
  225.             DrawOneEnt(1, curentity);
  226.                         break;
  227.         case 0x19:                /* P/previous object */
  228.             DrawOneEnt(0, curentity);
  229.             do {
  230.                 if (--curentity < 0) curentity = nextentity - 1;
  231.             } while (entityarray[curentity]->type == ENTITY_LIGHT);
  232.             DrawOneEnt(1, curentity);
  233.                         break;
  234.         case 0x22:                /* G/grid */
  235.             /* This was for manipulating a grid which could overlay the level.
  236.                The code sucked rocks, so it's been removed. */
  237.                         break;
  238.  
  239.                 }
  240.     } while (c != 0x1);
  241.  
  242.     MouseOff();
  243.         KillMouse();
  244.         InitScrn(M80x25x16);
  245. }
  246.  
  247. static void ReadVertices(void)
  248. {
  249.     int i, j, k;
  250.     int readcount;
  251.     vertex v;
  252.  
  253.     vlistx = Qmalloc(header.verticeslen/3);
  254.     vlisty = Qmalloc(header.verticeslen/3);
  255.     vlistz = Qmalloc(header.verticeslen/3);
  256.  
  257.     fseek(fi, header.vertices, SEEK_SET);
  258.  
  259.         for (i = 0, readcount = 0L; readcount < header.verticeslen; readcount += 12, i++) {
  260.         fread((char *)(&v), 1, 12, fi);
  261.         vlistx[i] = v.x;
  262.         vlisty[i] = v.y;
  263.         vlistz[i] = v.z;
  264.         }
  265.     vertexcount = i;
  266. }
  267.  
  268. static void ReadEdgeList(void)
  269. {
  270.     int i, j, k;
  271.     int readcount;
  272.     struct {
  273.         int start, end;
  274.     } edge;
  275.  
  276.     edgestart = Qmalloc(header.edgeslen/2);
  277.     edgeend  = Qmalloc(header.edgeslen/2);
  278.  
  279.     fseek(fi, header.edges, SEEK_SET);
  280.  
  281.     for (i = 0, readcount = 0L; readcount < header.edgeslen; readcount += 4, i++) {
  282.         fread((char *)(&edge), 1, 4, fi);
  283.         edgestart[i] = edge.start;
  284.         edgeend[i] = edge.end;
  285.         if (edge.start < 0 || edge.end < 0) i--;
  286.         }
  287.     edgecount = i;
  288. }
  289.  
  290. static void ReadEntList(void)
  291. {
  292.     entity *tt;
  293.     long int i;
  294.         char c;
  295.         char *type;
  296.     char *entry;
  297.     int x, y;
  298.  
  299.     maxlen = header.entitieslen;
  300.         if (header.id != 0x17)
  301.         Error("Not a valid .BSP file");
  302.  
  303.     fseek(fi, header.entities, SEEK_SET);
  304.     do {
  305.         tt = (entity *)Qmalloc(sizeof(entity));
  306.  
  307.         tt->classname = NULL;
  308.         tt->origin = NULL;
  309.         tt->model = NULL;
  310.         tt->light = NULL;
  311.         tt->angle = NULL;
  312.         tt->wad = NULL;
  313.         tt->style = NULL;
  314.         tt->spawnflags = NULL;
  315.  
  316.         skipspace(fi);
  317.         getopenbrace(fi);
  318.         nextchar(fi);
  319.  
  320.         if (fileend()) break;
  321.  
  322.         do {
  323.             putback = 1;
  324.             skipspace(fi);
  325.             type = getstring(fi);
  326.             skipspace(fi);
  327.             entry = getstring(fi);
  328.             skipspace(fi);
  329.             if (strcmp(type, "classname") == 0) tt->classname = entry;
  330.             if (strcmp(type, "origin") == 0) tt->origin = entry;
  331.             if (strcmp(type, "model") == 0) tt->model = entry;
  332.             if (strcmp(type, "light") == 0) tt->light = entry;
  333.             if (strcmp(type, "angle") == 0) tt->angle = entry;
  334.             if (strcmp(type, "style") == 0) tt->style = entry;
  335.             if (strcmp(type, "wad") == 0) tt->wad = entry;
  336.             if (strcmp(type, "spawnflags") == 0) tt->spawnflags = entry;
  337.  
  338.             c = nextchar(fi);
  339.         } while (c != '}' && c != EOF && c != '\0');
  340.  
  341.         if (tt->classname != NULL) {
  342.             if (strncmp(tt->classname, "weapon_", 7) == 0) tt->type = ENTITY_WEAPON;
  343.             else if (strncmp(tt->classname, "monster_", 7) == 0) tt->type = ENTITY_MONSTER;
  344.             else if (strncmp(tt->classname, "item_health", 11) == 0) tt->type = ENTITY_HEALTH;
  345.             else if (strncmp(tt->classname, "item_", 5) == 0) tt->type = ENTITY_ITEM;
  346.             else if (strcmp(tt->classname, "light") == 0) tt->type = ENTITY_LIGHT;
  347.             else if (strncmp(tt->classname, "light", 5) == 0) tt->type = ENTITY_VISILIGHT;
  348.             else if (strncmp(tt->classname, "info_player_start", 17) == 0) tt->type = ENTITY_START;
  349.             else if (strncmp(tt->classname, "info_player_deathmatch", 22) == 0) tt->type = ENTITY_DMSTART;
  350.             else tt->type = ENTITY_NONE;
  351.                 }
  352.  
  353.         if (tt->origin != NULL)
  354.             sscanf(tt->origin, "%ld%ld%ld", &(tt->x), &(tt->y), &(tt->z));
  355.  
  356.         entityarray[nextentity++] = tt;
  357.  
  358.         skipspace(fi);
  359.  
  360.     } while (!fileend());
  361. }
  362.  
  363. static void DrawScrnXOR(int blackify)
  364. {
  365.     long int x, y, z, s, so;
  366.     int i, color;
  367.  
  368.     blackify = 0;
  369.  
  370.     MouseOff();
  371.     if (blackify) DrawOneEnt(0, curentity);
  372.         MouseOff();
  373.  
  374.     for (i = 0; i < vertexcount; i++) UpdateVertexXOR(i, blackify);
  375.         for (i = 0; i < nextentity; i++) UpdateEntXOR(i, blackify);
  376.  
  377.     color = BLUE;
  378.     if (blackify == 1) color = BLACK;
  379.  
  380.     if (blackify != -2) {
  381.         i = (orgx * scale) >> 5;
  382.         LineXOR(320+i, 0, 320+i, 479, color);
  383.         i = (orgy * scale) >> 5;
  384.         LineXOR(0, 240-i, 639, 240-i, color);
  385.     }
  386.  
  387.     if (!blackify) DrawOneEnt(1, curentity);
  388.         MouseOn();
  389. }
  390.  
  391. static void DrawScrnMove(void)
  392. {
  393.     long int x, y, z, s, so;
  394.     int i;
  395.  
  396.     MouseOff();
  397.     DrawOneEnt(0, curentity);
  398.         MouseOff();
  399.  
  400.     for (i = 0; i < vertexcount; i++) {
  401.                 orgx += deltax;
  402.         orgy += deltay;
  403.         scale += deltascale;
  404.         UpdateVertexXOR(i, 0);
  405.         orgx -= deltax;
  406.         orgy -= deltay;
  407.         scale -= deltascale;
  408.         UpdateVertexXOR(i, 0);
  409.         }
  410.     for (i = 0; i < nextentity; i++) {
  411.                 orgx += deltax;
  412.         orgy += deltay;
  413.         scale += deltascale;
  414.         UpdateEntXOR(i, 0);
  415.         orgx -= deltax;
  416.         orgy -= deltay;
  417.         scale -= deltascale;
  418.         UpdateEntXOR(i, 0);
  419.         }
  420.  
  421.         orgx += deltax;
  422.     orgy += deltay;
  423.     scale += deltascale;
  424.         i = (orgx * scale) >> 5;
  425.     LineXOR(320+i, 0, 320+i, 479, BLUE);
  426.     i = (orgy * scale) >> 5;
  427.     LineXOR(0, 240-i, 639, 240-i, BLUE);
  428.     orgx -= deltax;
  429.     orgy -= deltay;
  430.     scale -= deltascale;
  431.     i = (orgx * scale) >> 5;
  432.     LineXOR(320+i, 0, 320+i, 479, BLUE);
  433.     i = (orgy * scale) >> 5;
  434.     LineXOR(0, 240-i, 639, 240-i, BLUE);
  435.  
  436.         orgx += deltax;
  437.     orgy += deltay;
  438.     scale += deltascale;
  439.  
  440.         deltax = deltay = deltascale = 0;
  441.  
  442.     DrawOneEnt(1, curentity);
  443.         MouseOn();
  444. }
  445.  
  446. static void DrawScrn(int blackify)
  447. {
  448.     int i, color;
  449.  
  450.     MouseOff();
  451.  
  452.     for (i = 0; i < nextentity; i++) UpdateEnt(i, blackify);
  453.     for (i = 0; i < vertexcount; i++) UpdateVertex(i, blackify);
  454.  
  455.     color = BLUE;
  456.     if (blackify == 1) color = BLACK;
  457.  
  458.         i = (orgx * scale) >> 5;
  459.     Line(320+i, 0, 320+i, 479, color);
  460.     i = (orgy * scale) >> 5;
  461.     Line(0, 240-i, 639, 240-i, color);
  462.  
  463.     if (!blackify) DrawOneEnt(1, curentity);
  464.         MouseOn();
  465. }
  466.  
  467. static void UpdateEdge(int i, int blackify)
  468. {
  469.     int x, y, color;
  470.     long int sx, sy, ex, ey;
  471.     long int dsx, dsy, dex, dey;
  472.  
  473.     sx = (long int)(vlistx[edgestart[i]]);
  474.     sy = (long int)(vlisty[edgestart[i]]);
  475.     ex = (long int)(vlistx[edgeend[i]]);
  476.     ey = (long int)(vlisty[edgeend[i]]);
  477.  
  478.     dsx = (((sx + orgx) * scale) >> 5);
  479.     dsy = (((sy + orgy) * scale) >> 5);
  480.     dex = (((ex + orgx) * scale) >> 5);
  481.     dey = (((ey + orgy) * scale) >> 5);
  482.  
  483.     color = GRAY;
  484.     if (blackify == 1) color = BLACK;
  485.  
  486.     Pixel(320+dsx, 240-dsy, color);
  487. }
  488.  
  489. static void UpdateEdgeXOR(int i, int blackify)
  490. {
  491.     int x, y, color;
  492.     long int sx, sy, ex, ey;
  493.     long int dsx, dsy, dex, dey;
  494.  
  495.     sx = (long int)(vlistx[edgestart[i]]);
  496.     sy = (long int)(vlisty[edgestart[i]]);
  497.     ex = (long int)(vlistx[edgeend[i]]);
  498.     ey = (long int)(vlisty[edgeend[i]]);
  499.  
  500.     dsx = (((sx + orgx) * scale) >> 5);
  501.     dsy = (((sy + orgy) * scale) >> 5);
  502.     dex = (((ex + orgx) * scale) >> 5);
  503.     dey = (((ey + orgy) * scale) >> 5);
  504.  
  505.     color = GRAY;
  506.     if (blackify == 1) color = BLACK;
  507.  
  508.         if (blackify != -2) {
  509.         PixelXOR(320+dsx, 240-dsy, color);
  510.         }
  511. }
  512.  
  513. static void UpdateVertex(int i, int blackify)
  514. {
  515.     int x, y, color;
  516.     long int vx, vy;
  517.  
  518.     vx = (long int)(vlistx[i]);
  519.     vy = (long int)(vlisty[i]);
  520.  
  521.     x = (((vx + orgx) * scale) >> 5);
  522.     y = (((vy + orgy) * scale) >> 5);
  523.  
  524.     color = GRAY;
  525.     if (blackify == 1) color = BLACK;
  526.  
  527.     Pixel(320+x, 240-y, color);
  528. }
  529.  
  530. static void UpdateVertexXOR(int i, int blackify)
  531. {
  532.     int x, y, color;
  533.     long int vx, vy;
  534.  
  535.     vx = (long int)(vlistx[i]);
  536.     vy = (long int)(vlisty[i]);
  537.  
  538.     x = (((vx + orgx) * scale) >> 5);
  539.     y = (((vy + orgy) * scale) >> 5);
  540.  
  541.     color = GRAY;
  542.     if (blackify == 1) color = BLACK;
  543.  
  544.         if (blackify != -2) {
  545.         PixelXOR(320+x, 240-y, color);
  546.         }
  547. }
  548.  
  549. static void UpdateEnt(int i, int blackify)
  550. {
  551.     int x, y, color;
  552.  
  553.     if (entityarray[i]->origin != NULL) {
  554.         x = (((entityarray[i]->x + orgx) * scale) >> 5);
  555.         y = (((entityarray[i]->y + orgy) * scale) >> 5);
  556.  
  557.         if (i == curentity) {
  558.             if (blackify == 0) BoxOutln(317+x, 237-y, 323+x, 243-y, LRED);
  559.             else BoxOutln(317+x, 237-y, 323+x, 243-y, BLACK);
  560.         }
  561.  
  562.         switch(entityarray[i]->type) {
  563.         case ENTITY_LIGHT:
  564.             color = WHITE;
  565.             if (blackify == 1) color = BLACK;
  566.             Pixel(320+x, 240-y, color);
  567.                         break;
  568.         case ENTITY_ITEM:
  569.             color = LBLUE;
  570.             if (blackify == 1) color = BLACK;
  571.             BoxFill(319+x, 239-y, 321+x, 241-y, color);
  572.             break;
  573.         case ENTITY_HEALTH:
  574.             color = LRED;
  575.             if (blackify == 1) color = BLACK;
  576.             Line(317+x, 240-y, 323+x, 240-y, color);
  577.             Line(320+x, 237-y, 320+x, 243-y, color);
  578.             break;
  579.         case ENTITY_START:
  580.             color = GREEN;
  581.             if (blackify == 1) color = BLACK;
  582.             BoxOutln(318+x, 238-y, 322+x, 242-y, color);
  583.             BoxFill(320+x, 240-y, 320+x, 240-y, color);
  584.             break;
  585.         case ENTITY_DMSTART:
  586.             color = LGREEN;
  587.             if (blackify == 1) color = BLACK;
  588.             BoxFill(319+x, 239-y, 321+x, 241-y, color);
  589.             break;
  590.         case ENTITY_WEAPON:
  591.             color = BROWN;
  592.             if (blackify == 1) color = BLACK;
  593.             BoxOutln(318+x, 238-y, 322+x, 242-y, color);
  594.             Pixel(320+x, 240-y, color);
  595.                         if (color == BROWN) color = YELLOW;
  596.             BoxOutln(319+x, 239-y, 321+x, 241-y, color);
  597.                         break;
  598.         case ENTITY_MONSTER:
  599.             color = LRED;
  600.             if (blackify == 1) color = BLACK;
  601.             Line(318+x, 238-y, 322+x, 242-y, color);
  602.             Line(318+x, 242-y, 322+x, 238-y, color);
  603.             Line(320+x, 240-y, 320+x, 240-y, color);
  604.             break;
  605.         case ENTITY_VISILIGHT:
  606.             color = WHITE;
  607.             if (blackify == 1) color = BLACK;
  608.             BoxFill(319+x, 239-y, 321+x, 241-y, color);
  609.                         break;
  610.                 default:
  611.             color = VIOLET;
  612.             if (blackify == 1) color = BLACK;
  613.             BoxFill(319+x, 239-y, 321+x, 241-y, color);
  614.             break;
  615.         }
  616.     }
  617. }
  618.  
  619. static void UpdateEntXOR(int i, int blackify)
  620. {
  621.     int x, y, color;
  622.  
  623.     if (entityarray[i]->origin != NULL) {
  624.         x = (((entityarray[i]->x + orgx) * scale) >> 5);
  625.         y = (((entityarray[i]->y + orgy) * scale) >> 5);
  626.  
  627.         if (blackify < 0)
  628.             BoxOutlnXOR(317+x, 237-y, 323+x, 243-y, LRED);
  629.  
  630.         if (blackify != -2) {
  631.             switch(entityarray[i]->type) {
  632.             case ENTITY_LIGHT:
  633.                 color = WHITE;
  634.                 if (blackify == 1) color = BLACK;
  635.                 PixelXOR(320+x, 240-y, color);
  636.                                 break;
  637.             case ENTITY_ITEM:
  638.                 color = LBLUE;
  639.                 if (blackify == 1) color = BLACK;
  640.                 BoxFillXOR(319+x, 239-y, 321+x, 241-y, color);
  641.                 break;
  642.             case ENTITY_HEALTH:
  643.                 color = LRED;
  644.                 if (blackify == 1) color = BLACK;
  645.                 LineXOR(317+x, 240-y, 323+x, 240-y, color);
  646.                 LineXOR(320+x, 237-y, 320+x, 243-y, color);
  647.                 break;
  648.             case ENTITY_START:
  649.                 color = GREEN;
  650.                 if (blackify == 1) color = BLACK;
  651.                 BoxOutlnXOR(318+x, 238-y, 322+x, 242-y, color);
  652.                 BoxFillXOR(320+x, 240-y, 320+x, 240-y, color);
  653.                 break;
  654.             case ENTITY_DMSTART:
  655.                 color = LGREEN;
  656.                 if (blackify == 1) color = BLACK;
  657.                 BoxFillXOR(319+x, 239-y, 321+x, 241-y, color);
  658.                 break;
  659.             case ENTITY_WEAPON:
  660.                 color = BROWN;
  661.                 if (blackify == 1) color = BLACK;
  662.                 BoxOutlnXOR(318+x, 238-y, 322+x, 242-y, color);
  663.                 PixelXOR(320+x, 240-y, color);
  664.                 if (color == BROWN) color = YELLOW;
  665.                 BoxOutlnXOR(319+x, 239-y, 321+x, 241-y, color);
  666.                                 break;
  667.             case ENTITY_MONSTER:
  668.                 color = LRED;
  669.                 if (blackify == 1) color = BLACK;
  670.                 LineXOR(318+x, 238-y, 322+x, 242-y, color);
  671.                 LineXOR(318+x, 242-y, 322+x, 238-y, color);
  672.                 LineXOR(320+x, 240-y, 320+x, 240-y, color);
  673.                 break;
  674.             case ENTITY_VISILIGHT:
  675.                 color = WHITE;
  676.                 if (blackify == 1) color = BLACK;
  677.                 BoxFillXOR(319+x, 239-y, 321+x, 241-y, color);
  678.                                 break;
  679.                         default:
  680.                 color = VIOLET;
  681.                                 if (blackify == 1) color = BLACK;
  682.                 BoxFillXOR(319+x, 239-y, 321+x, 241-y, color);
  683.                 break;
  684.             }
  685.         }
  686.         }
  687. }
  688.  
  689. static void DrawOneEnt(int highlight, int entity)
  690. {
  691.     long int x, y, z;
  692.     int i = entity, color;
  693.  
  694.     x = (((entityarray[i]->x + orgx) * scale) >> 5);
  695.     y = (((entityarray[i]->y + orgy) * scale) >> 5);
  696.  
  697.     MouseOff();
  698.     color = LRED;
  699.     if (entityarray[entity]->origin != NULL)
  700.         BoxOutlnXOR(317+x, 237-y, 323+x, 243-y, color);
  701.  
  702.     if (highlight) {
  703.         BoxFill(tbx+14, tby+411, tbx+306, tby+478, LGRAY);
  704.         BoxFill(tbx+1, tby+411, tbx+13, tby+478, GRAY);
  705.         BoxFill(tbx+307, tby+411, tbx+319, tby+478, GRAY);
  706.                 BoxOutln(tbx+0, tby+410, tbx+320, tby+479, WHITE);
  707.  
  708.         Gprintf(tbx+16, tby+415, Sans14N, BLACK, "#%d. \"%s\"", i, entityarray[i]->classname);
  709.  
  710.         x = tbx+16;
  711.         if (entityarray[i]->origin != NULL)
  712.             x = Gprintf(x, tby+430, Sans14N, BLACK, "(%s) ", entityarray[i]->origin);
  713.         if (entityarray[i]->angle != NULL)
  714.             Gprintf(x, tby+430, Sans14N, BLACK, "Angle=%s", entityarray[i]->angle);
  715.  
  716.         if (entityarray[i]->spawnflags != NULL)
  717.             Gprintf(tbx+16, tby+445, Sans14N, BLACK, "SpawnFlags=%s", entityarray[i]->spawnflags);
  718.  
  719.         x = tbx+16;
  720.         if (entityarray[i]->model != NULL)
  721.             x = Gprintf(x, tby+460, Sans14N, BLACK, "Model=%s ", entityarray[i]->model);
  722.         if (entityarray[i]->style != NULL)
  723.             Gprintf(x, tby+460, Sans14N, BLACK, "Style=%s", entityarray[i]->style);
  724.     }
  725.  
  726.         MouseOn();
  727. }
  728.  
  729. char WaitEvent(void)
  730. {
  731.     int i, j;
  732.  
  733.         while (1) {
  734.         if (KeyStatus()) return(ReadKeyScan());
  735.         else if (omb != (i = MouseButton())) {
  736.             ReadMouse();
  737.             omx = MouseX;
  738.             omy = MouseY;
  739.                         j = omb ^ i;
  740.             omb = i;
  741.             if ((j & 1) && (omb & 1)) return(0x7D);
  742.             if ((j & 1) && !(omb & 1)) return(0x7C);
  743.             if ((j & 2) && (omb & 2)) return(0x7B);
  744.             if ((j & 2) && !(omb & 2)) return(0x7A);
  745.                 }
  746.         else {
  747.             ReadMouse();
  748.  
  749.             if (omx != MouseX || omy != MouseY) {
  750.                 omx = MouseX;
  751.                 omy = MouseY;
  752.                 return(0x7E);
  753.                         }
  754.                 }
  755.         }
  756. }
  757.  
  758. int EventsPending(void)
  759. {
  760.     if (KeyStatus() || omb != MouseButton()) return(1);
  761.     ReadMouse();
  762.     if (omx != MouseX || omy != MouseY) return(1);
  763.     return(0);
  764. }
  765.  
  766. static void EditObject(void)
  767. {
  768.     DrawScrn(1);
  769.     DrawScrnXOR(0);
  770.     MouseOn();
  771. }
  772.  
  773. static void StatusUpdate(void)
  774. {
  775.     if (mouseready) MouseOff();
  776.     LimitY1 = 0;
  777.         BoxOutln(0, 0, 319, 18, WHITE);
  778.     BoxFill(1, 1, 318, 17, LGRAY);
  779.     BoxOutln(320, 0, 639, 18, WHITE);
  780.     BoxFill(321, 1, 638, 17, LGRAY);
  781.  
  782.     Gprintf(5, 2, Sans14N, BLACK, "%s", filename);
  783.     Gprintf(325, 2, Sans14N, BLACK, "Entities");
  784.     LimitY1 = 19;
  785.     if (mouseready) MouseOn();
  786. }
  787.  
  788.