1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 //
5 // This file has been modified from Ken Silverman's original release
6 // by Jonathon Fowler (jf@jonof.id.au)
7 // by the EDuke32 team (development@voidpoint.com)
8 
9 #include "build.h"
10 #include "editor.h"
11 
12 int32_t editorgridextent = 131072;
13 
14 ////////// editor side view //////////
15 int32_t m32_sideview = 0;
16 int32_t m32_sideelev = 256;  // elevation in BUILD degrees, 0..512
17 int16_t m32_sideang = 200;  // azimuth, 0..2047
18 
19 int32_t m32_sidecos, m32_sidesin;
20 int32_t m32_swcnt;
21 int32_t m32_wallscreenxy[MAXWALLS][2];
22 int16_t m32_wallsprite[MAXWALLS+MAXSPRITES];
23 static int32_t m32_sidedist[MAXWALLS+MAXSPRITES];
24 static vec3_t m32_viewplane;
25 
drawpixel_safe(void * s,char a)26 static void drawpixel_safe(void *s, char a)
27 {
28 #if defined __GNUC__
29     if (__builtin_expect((intptr_t) s >= frameplace && (intptr_t) s < frameplace+bytesperline*ydim, 1))
30 #else
31     if ((intptr_t) s >= frameplace && (intptr_t) s < frameplace+bytesperline*ydim)
32 #endif
33         drawpixel(s, a);
34 #ifdef DEBUGGINGAIDS
35     else
36     {
37         const char c = editorcolors[15];
38 
39         drawpixel((intptr_t *) frameplace, c);
40         drawpixel((intptr_t *) frameplace+1, c);
41         drawpixel((intptr_t *) frameplace+2, c);
42         drawpixel((intptr_t *) frameplace+bytesperline, c);
43         drawpixel((intptr_t *) frameplace+bytesperline+1, c);
44         drawpixel((intptr_t *) frameplace+bytesperline+2, c);
45         drawpixel((intptr_t *) frameplace+2*bytesperline, c);
46         drawpixel((intptr_t *) frameplace+2*bytesperline+1, c);
47         drawpixel((intptr_t *) frameplace+2*bytesperline+2, c);
48     }
49 #endif
50 }
51 
52 
53 
54 //
55 // plotpixel
56 //
plotpixel(int32_t x,int32_t y,char col)57 void plotpixel(int32_t x, int32_t y, char col)
58 {
59 #if defined USE_OPENGL && !defined EDUKE32_GLES
60     if (videoGetRenderMode() >= REND_POLYMOST && in3dmode())
61     {
62         palette_t p = paletteGetColor(col);
63         glEnable(GL_SCISSOR_TEST);
64         glScissor(x,ydim-y+1,1,1);
65         glClearColor((float)p.r*(1.0f/255.0f),(float)p.g*(1.0f/255.0f),(float)p.b*(1.0f)/255.0f,1.0f);
66         glClear(GL_COLOR_BUFFER_BIT);
67         glClearColor(0.0f,0.0f,0.0f,1.0f); // XXX: there must be a better way
68         glDisable(GL_SCISSOR_TEST);
69         return;
70     }
71 #endif
72 
73     videoBeginDrawing(); //{{{
74     drawpixel_safe((void *) (ylookup[y]+x+frameplace), col);
75     videoEndDrawing();   //}}}
76 }
77 
plotlines2d(const int32_t * xx,const int32_t * yy,int32_t numpoints,int col)78 void plotlines2d(const int32_t *xx, const int32_t *yy, int32_t numpoints, int col)
79 {
80     int32_t i;
81 
82 #ifdef USE_OPENGL
83     if (videoGetRenderMode() >= REND_POLYMOST && in3dmode())
84     {
85         palette_t p = paletteGetColor(col);
86 
87         polymost_useColorOnly(true);
88         glBegin(GL_LINE_STRIP);
89 
90         glColor4ub(p.r, p.g, p.b, 1);
91 
92         for (i=0; i<numpoints; i++)
93             glVertex2i(xx[i], yy[i]);
94 
95         glEnd();
96         polymost_useColorOnly(false);
97         return;
98     }
99 #endif
100     {
101         int32_t odrawlinepat = drawlinepat;
102         drawlinepat = 0xffffffff;
103 
104         videoBeginDrawing();
105         for (i=0; i<numpoints-1; i++)
106             editorDraw2dLine(xx[i], yy[i], xx[i+1], yy[i+1], col);
107         videoEndDrawing();
108 
109         drawlinepat = odrawlinepat;
110     }
111 }
112 
113 
114 //
115 // drawline256
116 //
117 #ifdef USE_OPENGL
drawlinegl(int32_t x1,int32_t y1,int32_t x2,int32_t y2,palette_t p)118 static void drawlinegl(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p)
119 {
120     //        setpolymost2dview();	// JBF 20040205: more efficient setup
121 
122     int const dx = x2-x1;
123     int const dy = y2-y1;
124 
125     if (dx >= 0)
126     {
127         if ((x1 >= wx2) || (x2 < wx1)) return;
128         if (x1 < wx1) y1 += scale(wx1-x1, dy, dx), x1 = wx1;
129         if (x2 > wx2) y2 += scale(wx2-x2, dy, dx), x2 = wx2;
130     }
131     else
132     {
133         if ((x2 >= wx2) || (x1 < wx1)) return;
134         if (x2 < wx1) y2 += scale(wx1-x2, dy, dx), x2 = wx1;
135         if (x1 > wx2) y1 += scale(wx2-x1, dy, dx), x1 = wx2;
136     }
137     if (dy >= 0)
138     {
139         if ((y1 >= wy2) || (y2 < wy1)) return;
140         if (y1 < wy1) x1 += scale(wy1-y1, dx, dy), y1 = wy1;
141         if (y2 > wy2) x2 += scale(wy2-y2, dx, dy), y2 = wy2;
142     }
143     else
144     {
145         if ((y2 >= wy2) || (y1 < wy1)) return;
146         if (y2 < wy1) x2 += scale(wy1-y2, dx, dy), y2 = wy1;
147         if (y1 > wy2) x1 += scale(wy2-y1, dx, dy), y1 = wy2;
148     }
149 
150     glViewport(0, 0, xdim, ydim);
151     glMatrixMode(GL_PROJECTION);
152     glLoadIdentity();
153     glOrtho(0, xdim, ydim, 0, -1, 1);
154     if (videoGetRenderMode() == REND_POLYMER)
155     {
156         glMatrixMode(GL_MODELVIEW);
157         glLoadIdentity();
158     }
159 
160     polymost2d = 1;
161     glDisable(GL_ALPHA_TEST);
162     glDisable(GL_DEPTH_TEST);
163     glEnable(GL_BLEND);	// When using line antialiasing, this is needed
164 
165     polymost_useColorOnly(true);
166     glBegin(GL_LINES);
167     glColor4ub(p.r, p.g, p.b, 255);
168 
169     glVertex2f((float) x1 * (1.f/4096.f), (float) y1 * (1.f/4096.f));
170     glVertex2f((float) x2 * (1.f/4096.f), (float) y2 * (1.f/4096.f));
171 
172     glEnd();
173     polymost_useColorOnly(false);
174 }
175 #endif
176 
drawlinepixels(int32_t x1,int32_t y1,int32_t x2,int32_t y2,char col)177 static void drawlinepixels(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
178 {
179     int32_t dx, dy, i, j, inc, plc, daend;
180     intptr_t p;
181 
182     dx = x2-x1; dy = y2-y1;
183     if (dx >= 0)
184     {
185         if ((x1 >= wx2) || (x2 < wx1)) return;
186         if (x1 < wx1) y1 += scale(wx1-x1, dy, dx), x1 = wx1;
187         if (x2 > wx2) y2 += scale(wx2-x2, dy, dx), x2 = wx2;
188     }
189     else
190     {
191         if ((x2 >= wx2) || (x1 < wx1)) return;
192         if (x2 < wx1) y2 += scale(wx1-x2, dy, dx), x2 = wx1;
193         if (x1 > wx2) y1 += scale(wx2-x1, dy, dx), x1 = wx2;
194     }
195     if (dy >= 0)
196     {
197         if ((y1 >= wy2) || (y2 < wy1)) return;
198         if (y1 < wy1) x1 += scale(wy1-y1, dx, dy), y1 = wy1;
199         if (y2 > wy2) x2 += scale(wy2-y2, dx, dy), y2 = wy2;
200     }
201     else
202     {
203         if ((y2 >= wy2) || (y1 < wy1)) return;
204         if (y2 < wy1) x2 += scale(wy1-y2, dx, dy), y2 = wy1;
205         if (y1 > wy2) x1 += scale(wy2-y1, dx, dy), y1 = wy2;
206     }
207 
208     if (klabs(dx) >= klabs(dy))
209     {
210         if (dx == 0) return;
211         if (dx < 0)
212         {
213             i = x1; x1 = x2; x2 = i;
214             i = y1; y1 = y2; y2 = i;
215         }
216 
217         inc = divscale12(dy, dx);
218         plc = y1+mulscale12((2047-x1)&4095, inc);
219         i = ((x1+2048)>>12); daend = ((x2+2048)>>12);
220 
221         videoBeginDrawing(); //{{{
222         for (; i<daend; i++)
223         {
224             j = (plc>>12);
225             if ((j >= startumost[i]) && (j < startdmost[i]))
226                 drawpixel_safe((void *) (frameplace+ylookup[j]+i), col);
227             plc += inc;
228         }
229         videoEndDrawing();   //}}}
230     }
231     else
232     {
233         if (dy < 0)
234         {
235             i = x1; x1 = x2; x2 = i;
236             i = y1; y1 = y2; y2 = i;
237         }
238 
239         inc = divscale12(dx, dy);
240         plc = x1+mulscale12((2047-y1)&4095, inc);
241         i = ((y1+2048)>>12); daend = ((y2+2048)>>12);
242 
243         videoBeginDrawing(); //{{{
244         p = ylookup[i]+frameplace;
245         for (; i<daend; i++)
246         {
247             j = (plc>>12);
248             if ((i >= startumost[j]) && (i < startdmost[j]))
249                 drawpixel_safe((void *) (j+p), col);
250             plc += inc; p += ylookup[1];
251         }
252         videoEndDrawing();   //}}}
253     }
254 }
255 
drawlinergb(int32_t x1,int32_t y1,int32_t x2,int32_t y2,palette_t p)256 void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p)
257 {
258 #ifdef USE_OPENGL
259     if (videoGetRenderMode() >= REND_POLYMOST)
260     {
261         drawlinegl(x1, y1, x2, y2, p);
262         return;
263     }
264 #endif
265 
266     char const col = palookup[0][p.f];
267     drawlinepixels(x1, y1, x2, y2, col);
268 }
269 
renderDrawLine(int32_t x1,int32_t y1,int32_t x2,int32_t y2,char col)270 void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
271 {
272     col = palookup[0][col];
273 
274 #ifdef USE_OPENGL
275     if (videoGetRenderMode() >= REND_POLYMOST)
276     {
277         palette_t p = paletteGetColor(col);
278         p.f = col;
279         drawlinegl(x1, y1, x2, y2, p);
280         return;
281     }
282 #endif
283 
284     drawlinepixels(x1, y1, x2, y2, col);
285 }
286 
287 
288 //static void attach_here() {}
289 
290 //
291 // drawline16
292 //
293 // JBF: Had to add extra tests to make sure x-coordinates weren't winding up -'ve
294 //   after clipping or crashes would ensue
295 uint32_t drawlinepat = 0xffffffff;
296 
editorDraw2dLine(int32_t x1,int32_t y1,int32_t x2,int32_t y2,int col)297 int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col)
298 {
299     //int32_t odx,ody;
300     //int32_t ox1=x1,oy1=y1, ox2=x2,oy2=y2;
301 
302     vec2_t d = { x2-x1, y2-y1 };
303 
304     //odx=dx;
305     //ody=dy;
306 
307     if (d.x < 0)
308     {
309         swaplong(&x1, &x2);
310         swaplong(&y1, &y2);
311     }
312 
313     if (x1 >= xdim || x2 < 0)
314         return 0;
315 
316     if (x1 < 0)
317     {
318         if (d.y) y1 += scale(0-x1, d.y, d.x);
319         x1 = 0;
320     }
321 
322     if (x2 >= xdim)
323     {
324         if (d.y) y2 += scale(xdim-1-x2, d.y, d.x);
325         x2 = xdim-1;
326     }
327 
328     if ((d.x < 0 && d.y >= 0) || (d.y < 0 && d.x >= 0))
329     {
330         swaplong(&x1, &x2);
331         swaplong(&y1, &y2);
332     }
333 
334     if (y1 >= ydim16 || y2 < 0)
335         return 0;
336 
337     if (y1 < 0)
338     {
339         if (d.x)
340             x1 = clamp(x1 + scale(0 - y1, d.x, d.y), 0, xdim - 1);
341         y1 = 0;
342     }
343 
344     if (y2 >= ydim16)
345     {
346         if (d.x)
347             x2 = clamp(x2 + scale(ydim16-1-y2, d.x, d.y), 0, xdim-1);
348         y2 = ydim16-1;
349     }
350 
351     if (d.y < 0)
352     {
353         swaplong(&x1, &x2);
354         swaplong(&y1, &y2);
355     }
356 
357     //if (ox1||ox2||oy1||oy2)
358     //    if (x1<0||x1>=xdim || y2<0||y2>=ydim)
359     //        attach_here();
360 
361     d.x = klabs(x2-x1)+1;
362     d.y = klabs(y2-y1)+1;
363 
364     if ((d.x >= d.y && x2 < x1) || (d.x < d.y && y2 < y1))
365     {
366         swaplong(&x1, &x2);
367         swaplong(&y1, &y2);
368     }
369 
370     int pinc, inc = 1;
371 
372     videoBeginDrawing(); //{{{
373 
374     intptr_t p = (y1*bytesperline)+x1+frameplace;
375 
376     if (d.x >= d.y)
377     {
378         pinc = (y2 > y1) ? bytesperline : -bytesperline;
379     }
380     else
381     {
382         pinc = (x2 > x1) ? 1 : -1;
383         swaplong(&d.x, &d.y);
384         inc = bytesperline;
385     }
386 
387     int const trans = (col < 0);
388 
389     if (trans)
390     {
391         col = -col;
392 
393         if (drawlinepat == 0xffffffff)
394         {
395             for (bssize_t i=d.x, df=0; i>0; i--)
396             {
397                 drawtranspixel((char *) p, col);
398                 df += d.y;
399                 if (df >= d.x) { df -= d.x; p += pinc; }
400                 p += inc;
401             }
402         }
403         else
404         {
405             uint32_t patc = UINT_MAX;
406 
407             for (bssize_t i=d.x, df=0; i>0; i--)
408             {
409                 if (drawlinepat & pow2long[(++patc)&31])
410                     drawtranspixel((char *) p, col);
411                 df += d.y;
412                 if (df >= d.x) { df -= d.x; p += pinc; }
413                 p += inc;
414             }
415         }
416 
417         videoEndDrawing();   //}}}
418 
419         return 1;
420     }
421 
422     if (inc == 1 && d.y == 1 && drawlinepat == 0xffffffff)
423         clearbufbyte((void *) p, d.x, ((int32_t) col<<24)|((int32_t) col<<16)|((int32_t) col<<8)|col);
424     else if (drawlinepat == 0xffffffff)
425     {
426         for (bssize_t i=d.x, df=0; i>0; i--)
427         {
428             drawpixel((char *) p, col);
429             df += d.y;
430             if (df >= d.x) { df -= d.x; p += pinc; }
431             p += inc;
432         }
433     }
434     else
435     {
436         uint32_t patc = UINT_MAX;
437 
438         for (bssize_t i=d.x, df=0; i>0; i--)
439         {
440             if (drawlinepat & pow2long[(++patc)&31])
441                 drawpixel((char *) p, col);
442             df += d.y;
443             if (df >= d.x) { df -= d.x; p += pinc; }
444             p += inc;
445         }
446     }
447 
448     videoEndDrawing();   //}}}
449 
450     return 1;
451 }
452 
editorDraw2dLineMiddle(int32_t x1,int32_t y1,int32_t x2,int32_t y2,char col)453 static FORCE_INLINE void editorDraw2dLineMiddle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
454 {
455     editorDraw2dLine(halfxdim16+x1, midydim16+y1, halfxdim16+x2, midydim16+y2, col);
456 }
457 
458 // eccen: eccentricity of the ellipse,
459 //   16384: circle
460 //  <16384: shrink in y
461 //  >16384: grow in y
editorDraw2dCircle(int32_t x1,int32_t y1,int32_t r,int32_t eccen,char col)462 void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char col)
463 {
464     if (eccen != 16384)
465     {
466         // JonoF's rough approximation of a circle
467         int32_t l, spx, spy, lpx, lpy, px, py;
468 
469         spx = lpx = x1 + mulscale14(r, sintable[0]);
470         spy = lpy = y1 + mulscale14(eccen, mulscale14(r, sintable[512]));
471 
472         for (l=64; l<2048; l+=64)
473         {
474             px = x1 + mulscale14(r, sintable[l]);
475             py = y1 + mulscale14(eccen, mulscale14(r, sintable[(l+512)&2047]));
476 
477             editorDraw2dLine(lpx, lpy, px, py, col);
478 
479             lpx = px;
480             lpy = py;
481         }
482 
483         editorDraw2dLine(lpx, lpy, spx, spy, col);
484 
485         return;
486     }
487 
488     if (r < 0) r = -r;
489     if (x1+r < 0 || y1+r < 0 || x1-r >= xdim || y1-r >= ydim16) return;
490 
491     uint32_t const uxdim = xdim, uydim16 = ydim16;
492 
493     /*
494     *      d
495     *    6 | 7
496     *   \  |  /
497     *  5  \|/  8
498     * c----+----a
499     *  4  /|\  1
500     *   /  |  \
501     *    3 | 2
502     *      b
503     */
504 
505     videoBeginDrawing();
506     intptr_t const p = (y1*bytesperline)+x1+frameplace;
507 
508     uint32_t patc = UINT_MAX;
509 
510     if (drawlinepat == 0xffffffff || drawlinepat & pow2long[(++patc)&31])
511     {
512         if ((uint32_t) y1 < uydim16 && (uint32_t) (x1+r) < uxdim)
513             drawpixel((char *) (p+r), col);    // a
514         if ((uint32_t) x1 < uxdim   && (uint32_t) (y1+r) < uydim16)
515             drawpixel((char *) (p+(r*bytesperline)), col);    // b
516         if ((uint32_t) y1 < uydim16 && (uint32_t) (x1-r) < uxdim)
517             drawpixel((char *) (p-r), col);    // c
518         if ((uint32_t) x1 < uxdim   && (uint32_t) (y1-r) < uydim16)
519             drawpixel((char *) (p-(r*bytesperline)), col);    // d
520     }
521 
522     int32_t xp = 0, yp = r;
523     int32_t d = 1 - r, de = 2, dse = 5 - (r << 1);
524 
525     if (drawlinepat != 0xffffffff)
526     {
527         do
528         {
529             if (d < 0)
530             {
531                 d += de;
532                 dse += 2;
533             }
534             else
535             {
536                 d += dse;
537                 dse += 4;
538                 yp--;
539             }
540 
541             xp++;
542             de += 2;
543 
544             int32_t const ypbpl = yp*bytesperline;
545             int32_t const xpbpl = xp*bytesperline;
546 
547             if (drawlinepat & pow2long[(++patc) & 31])
548             {
549                 if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
550                     drawpixel_safe((char *) (p + yp + xpbpl), col);  // 1
551                 if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
552                     drawpixel_safe((char *) (p + xp + ypbpl), col);  // 2
553                 if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
554                     drawpixel_safe((char *) (p - xp + ypbpl), col);  // 3
555                 if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
556                     drawpixel_safe((char *) (p - yp + xpbpl), col);  // 4
557                 if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
558                     drawpixel_safe((char *) (p - yp - xpbpl), col);  // 5
559                 if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
560                     drawpixel_safe((char *) (p - xp - ypbpl), col);  // 6
561                 if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
562                     drawpixel_safe((char *) (p + xp - ypbpl), col);  // 7
563                 if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
564                     drawpixel_safe((char *) (p + yp - xpbpl), col);  // 8
565             }
566         } while (yp > xp);
567 
568         videoEndDrawing();
569         return;
570     }
571 
572     do
573     {
574         if (d < 0)
575         {
576             d += de;
577             dse += 2;
578         }
579         else
580         {
581             d += dse;
582             dse += 4;
583             yp--;
584         }
585 
586         xp++;
587         de += 2;
588 
589         int32_t const ypbpl = yp*bytesperline;
590         int32_t const xpbpl = xp*bytesperline;
591 
592         if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
593             drawpixel_safe((char *) (p + yp + xpbpl), col);  // 1
594         if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
595             drawpixel_safe((char *) (p + xp + ypbpl), col);  // 2
596         if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
597             drawpixel_safe((char *) (p - xp + ypbpl), col);  // 3
598         if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
599             drawpixel_safe((char *) (p - yp + xpbpl), col);  // 4
600         if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
601             drawpixel_safe((char *) (p - yp - xpbpl), col);  // 5
602         if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
603             drawpixel_safe((char *) (p - xp - ypbpl), col);  // 6
604         if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
605             drawpixel_safe((char *) (p + xp - ypbpl), col);  // 7
606         if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
607             drawpixel_safe((char *) (p + yp - xpbpl), col);  // 8
608     } while (yp > xp);
609 
610     videoEndDrawing();
611 }
612 
613 //
614 // clear2dscreen
615 //
clear2dscreen(void)616 void clear2dscreen(void)
617 {
618     int32_t const clearsz = (ydim16 <= ydim - STATUS2DSIZ2) ? ydim - STATUS2DSIZ2 : ydim;
619     videoBeginDrawing();  //{{{
620     Bmemset((char *) frameplace, 0, bytesperline*clearsz);
621     videoEndDrawing();   //}}}
622 }
623 
624 
625 ////////// editor side view //////////
626 
scalescreeny(int32_t sy)627 int32_t scalescreeny(int32_t sy) { return (m32_sideview) ? mulscale14(sy, m32_sidesin) : sy; }
628 
629 // return screen coordinates for BUILD coords x and y (relative to current position)
editorGet2dScreenCoordinates(int32_t * xres,int32_t * yres,int32_t x,int32_t y,int32_t zoome)630 void editorGet2dScreenCoordinates(int32_t *xres, int32_t *yres, int32_t x, int32_t y, int32_t zoome)
631 {
632     vec2_t coord = { x, y };
633 
634     if (m32_sideview)
635         rotatevec(coord, m32_sideang, &coord);
636 
637     *xres = mulscale14(coord.x, zoome);
638     *yres = scalescreeny(mulscale14(coord.y, zoome));
639 }
640 
641 #if 0
642 void invscreencoords(int32_t *dx, int32_t *dy, int32_t sx, int32_t sy, int32_t zoome)
643 {
644     if (m32_sidesin==0 || zoome==0) { *dx=0; *dy=0; return; }
645 
646     sy = divscale14(divscale14(sy, m32_sidesin), zoome);
647     sx = divscale14(sx, zoome);
648 
649     rotatepoint(0, 0, sx, sy, -m32_sideang, dx, dy);
650 }
651 #endif
652 
653 // invscreencoords with sx==0 and sy==getscreenvdisp(dz, zoom)
getinvdisplacement(int32_t * dx,int32_t * dy,int32_t dz)654 int32_t getinvdisplacement(int32_t *dx, int32_t *dy, int32_t dz)
655 {
656     if (m32_sidesin==0)
657         return 1;
658 
659     dz = (((int64_t) dz * (int64_t) m32_sidecos)/(int64_t) m32_sidesin)>>4;
660 
661     vec2_t v[2] = { { 0, dz },{ *dx, *dy } };
662 
663     rotatevec(v[0], -m32_sideang, &v[1]);
664 
665     *dx = v[1].x;
666     *dy = v[1].y;
667 
668     return 0;
669 }
670 
671 // return vertical screen coordinate displacement for BUILD z coord
getscreenvdisp(int32_t bz,int32_t zoome)672 int32_t getscreenvdisp(int32_t bz, int32_t zoome)
673 {
674     return mulscale32(bz, zoome*m32_sidecos);
675 }
676 
editorSetup2dSideView(void)677 void editorSetup2dSideView(void)
678 {
679     if (m32_sideview)
680     {
681         m32_viewplane.x = 0;
682         m32_viewplane.y = -512;
683 
684         m32_sidesin = sintable[m32_sideelev&2047];
685         m32_sidecos = sintable[(m32_sideelev+512)&2047];
686 
687         rotatevec(m32_viewplane.vec2, -m32_sideang, &m32_viewplane.vec2);
688         m32_viewplane.x = mulscale14(m32_viewplane.x, m32_sidecos);
689         m32_viewplane.y = mulscale14(m32_viewplane.y, m32_sidecos);
690         m32_viewplane.z = m32_sidesin>>5;
691     }
692 }
693 
editorGet2dSideViewDistance(int16_t sw,int16_t sect)694 static void editorGet2dSideViewDistance(int16_t sw, int16_t sect)
695 {
696     vec3_t *p;
697     vec3_t v;
698 
699     if (sw<MAXWALLS)
700     {
701         v.x = (wall[sw].x + wall[wall[sw].point2].x)>>1;
702         v.y = (wall[sw].y + wall[wall[sw].point2].y)>>1;
703         v.z = getflorzofslope(sect, v.x, v.y);
704         p = &v;
705     }
706     else
707         p = &sprite[sw-MAXWALLS].pos;
708 
709     m32_sidedist[sw] = p->x*m32_viewplane.x + p->y*m32_viewplane.y + (p->z>>4)*m32_viewplane.z;
710 }
711 
editorCompare2dSideViewPoints(const void * sw1,const void * sw2)712 static int editorCompare2dSideViewPoints(const void *sw1, const void *sw2)
713 {
714     int32_t dist1 = m32_sidedist[B_UNBUF16(sw1)];
715     int32_t dist2 = m32_sidedist[B_UNBUF16(sw2)];
716 
717     if (dist2>dist1)
718         return 1;
719     else if (dist1>dist2)
720         return -1;
721 
722     //    if (*sw1<MAXWALLS && *sw2<MAXWALLS)
723     //        return (wall[*sw2].nextwall>=0) - (wall[*sw1].nextwall>=0);
724 
725     return 0;
726 }
727 
728 //
729 // draw2dgrid
730 //
editorDraw2dGrid(int32_t posxe,int32_t posye,int32_t posze,int16_t cursectnum,int16_t ange,int32_t zoome,int16_t gride)731 void editorDraw2dGrid(int32_t posxe, int32_t posye, int32_t posze, int16_t cursectnum, int16_t ange, int32_t zoome, int16_t gride)
732 {
733     int64_t i, xp1, yp1, xp2=0, yp2, tempy;
734 
735     UNREFERENCED_PARAMETER(ange);
736 
737     if (gride <= 0)
738         return;
739 
740     videoBeginDrawing();	//{{{
741 
742     if (m32_sideview)
743     {
744         int32_t sx1, sy1, sx2, sy2, dx=0, dy=0;
745         int32_t xinc=0, yinc=2048>>gride, yofs;
746 
747         //        yofs = getscreenvdisp((yinc-posze)&((yinc<<4)-1), zoome);
748         if (cursectnum<0 || cursectnum>=numsectors)
749             yofs = getscreenvdisp(-posze, zoome);
750         else
751             yofs = getscreenvdisp(getflorzofslope(cursectnum, posxe, posye)-posze, zoome);
752 
753         while (scalescreeny(mulscale14(yinc, zoome))==0 && gride>2)
754         {
755             gride--;
756             yinc = 2048>>gride;
757         }
758 
759         xp2 = xp1 = ((posxe + (1024 >> gride)) & -(((int64_t)(1)) << (11 - gride)));
760         yp2 = yp1 = ((posye + (1024 >> gride)) & -(((int64_t)(1)) << (11 - gride)));
761 
762         do
763         {
764             if (xinc==0)
765             {
766                 editorGet2dScreenCoordinates(&sx1, &sy1, -editorgridextent-posxe, yp2-posye, zoome);
767                 if (yp2 == yp1)
768                 {
769                     editorGet2dScreenCoordinates(&sx2, &sy2, editorgridextent-posxe, yp2-posye, zoome);
770                     dx = sx2-sx1;
771                     dy = sy2-sy1;
772                 }
773                 yp2 += yinc;
774             }
775             else  // if (yinc==0)
776             {
777                 editorGet2dScreenCoordinates(&sx1, &sy1, xp2-posxe, -editorgridextent-posye, zoome);
778                 if (xp2 == xp1)
779                 {
780                     editorGet2dScreenCoordinates(&sx2, &sy2, xp2-posxe, editorgridextent-posye, zoome);
781                     dx = sx2-sx1;
782                     dy = sy2-sy1;
783                 }
784                 xp2 += xinc;
785             }
786 
787             i = editorDraw2dLine(halfxdim16+sx1, midydim16+sy1+yofs, halfxdim16+sx1+dx, midydim16+sy1+dy+yofs, editorcolors[25]);
788             if (i==0 || (xp2<-editorgridextent || xp2>editorgridextent ||
789                 yp2<-editorgridextent || yp2>editorgridextent))
790             {
791                 xp2 = xp1;
792                 yp2 = yp1;
793 
794                 i = 1;
795 
796                 if (yinc>0)
797                     yinc *= -1;
798                 else if (yinc<0)
799                 {
800                     xinc = -yinc;
801                     yinc = 0;
802                 }
803                 else if (xinc>0)
804                     xinc *= -1;
805                 else // if (xinc<0)
806                     i = 0;
807             }
808         } while (i);
809     }
810     else
811     {
812         // vertical lines
813         yp1 = midydim16-mulscale14(posye+editorgridextent, zoome);
814         if (yp1 < 0) yp1 = 0;
815 
816         yp2 = midydim16-mulscale14(posye-editorgridextent, zoome);
817         if (yp2 >= ydim16) yp2 = ydim16-1;
818 
819         if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1))
820         {
821             xp1 = halfxdim16-mulscale14(posxe+editorgridextent, zoome);
822 
823             for (i=-editorgridextent; i<=editorgridextent; i+=(2048>>gride))
824             {
825                 xp2 = xp1;
826                 xp1 = halfxdim16-mulscale14(posxe-i, zoome);
827 
828                 if (xp1 >= xdim)
829                     break;
830 
831                 if (xp1 >= 0)
832                 {
833                     if (xp1 != xp2)
834                         editorDraw2dLine(xp1, yp1, xp1, yp2, editorcolors[25]);
835                 }
836             }
837             if (i >= editorgridextent && xp1 < xdim)
838                 xp2 = xp1;
839             if (xp2 >= 0 && xp2 < xdim)
840                 editorDraw2dLine(xp2, yp1, xp2, yp2, editorcolors[25]);
841         }
842 
843         // horizontal lines
844         xp1 = mulscale14(posxe+editorgridextent, zoome);
845         xp2 = mulscale14(posxe-editorgridextent, zoome);
846         tempy = 0x80000000l;
847 
848         for (i=-editorgridextent; i<=editorgridextent; i+=(2048>>gride))
849         {
850             yp1 = ((posye-i)*zoome)>>14;
851             if (yp1 != tempy)
852             {
853                 if ((yp1 > midydim16-ydim16) && (yp1 <= midydim16))
854                 {
855                     editorDraw2dLineMiddle(-xp1, -yp1, -xp2, -yp1, editorcolors[25]);
856                     tempy = yp1;
857                 }
858             }
859         }
860     }
861 
862     videoEndDrawing();   //}}}
863 }
864 
865 
editorDraw2dWall(int32_t i,int32_t posxe,int32_t posye,int32_t posze,int32_t zoome,int32_t grayp)866 static void editorDraw2dWall(int32_t i, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome, int32_t grayp)
867 {
868     const walltype *const wal = &wall[i];
869 
870     int32_t j = wal->nextwall;
871     int32_t cstat = 0;
872 #if 0
873     if (editstatus == 0)
874     {
875         if ((show2dwall[i>>3]&pow2char[i&7]) == 0) return;
876         if ((j >= 0) && (i > j))
877             if ((show2dwall[j>>3]&pow2char[j&7]) > 0) return;
878     }
879     else
880 #endif
881     {
882         if (!m32_sideview && !(grayp&2) && (j >= 0) && (i > j)) return;
883     }
884 
885     char col;
886 
887     if (grayp&1)
888         col = editorcolors[8];
889     else if (j < 0)
890     {
891         col = (i == linehighlight) ? editorcolors[15] - M32_THROB : editorcolors[15];
892         cstat = wal->cstat;
893     }
894     else
895     {
896         if ((unsigned) wal->nextwall < MAXWALLS && ((wal->cstat^wall[j].cstat)&1))
897             col = editorcolors[2];
898         else if (bloodhack ? (wal->cstat&64) != 0 : (wal->cstat&1) != 0)
899             col = editorcolors[5];
900         else col = editorcolors[4];
901 
902         cstat = wal->cstat;
903         if (i != linehighlight && (unsigned)wal->nextwall < MAXWALLS)
904         {
905             if (wal->nextwall == linehighlight)
906                 cstat = wall[wal->nextwall].cstat;
907             else
908                 cstat |= wall[wal->nextwall].cstat;
909         }
910 
911         if (i == linehighlight || (linehighlight >= 0 && i == wall[linehighlight].nextwall))
912             col += M32_THROB>>2;
913     }
914 
915     if (bloodhack && (cstat&0xc000))
916     {
917         if (cstat&0x8000)
918             col = editorcolors[10];
919         else if (cstat&0x4000)
920             col = editorcolors[9];
921         if (i == linehighlight || (linehighlight >= 0 && i == wall[linehighlight].nextwall))
922             col -= M32_THROB>>3;
923     }
924 
925     int const p2 = wal->point2;
926 
927     int32_t x1, y1, x2, y2;
928     editorGet2dScreenCoordinates(&x1, &y1, wal->x-posxe, wal->y-posye, zoome);
929     editorGet2dScreenCoordinates(&x2, &y2, wall[p2].x-posxe, wall[p2].y-posye, zoome);
930 
931     int64_t const dx = wal->x-wall[p2].x;
932     int64_t const dy = wal->y-wall[p2].y;
933     int64_t const dist = dx*dx + dy*dy;
934 
935     int const bothSidesHighlighted = ((show2dwall[i>>3]&pow2char[i&7]) && (show2dwall[p2>>3]&pow2char[p2&7]));
936 
937     if (dist > INT32_MAX)
938     {
939         col=editorcolors[9];
940         if (i == linehighlight || (linehighlight >= 0 && i == wall[linehighlight].nextwall))
941             col -= M32_THROB>>3;
942     }
943     else if ((showfirstwall && searchsector>=0 && (sector[searchsector].wallptr == i ||
944         sector[searchsector].wallptr == wal->nextwall)) ||
945         bothSidesHighlighted)
946     {
947         col = editorcolors[14];
948         if (i == linehighlight || (linehighlight >= 0 && i == wall[linehighlight].nextwall) || bothSidesHighlighted)
949             col -= M32_THROB>>1;
950     }
951     else if (circlewall >= 0 && (i == circlewall || wal->nextwall == circlewall))
952         col = editorcolors[14];
953 
954     int32_t fz=0, fzn=0;
955 
956     if (m32_sideview)
957     {
958         // draw vertical line to neighboring wall
959         int32_t const sect = sectorofwall(i);
960 
961         fz = getflorzofslope(sect, wal->x, wal->y);
962         int32_t fz2 = getflorzofslope(sect, wall[p2].x, wall[p2].y);
963 
964         int32_t const dz = getscreenvdisp(fz-posze, zoome);
965         int32_t const dz2 = getscreenvdisp(fz2-posze, zoome);
966 
967         y1 += dz;
968         y2 += dz2;
969 
970         if (wal->nextwall>=0)
971         {
972             fzn = getflorzofslope(wal->nextsector, wal->x, wal->y);
973             //            if (i < wall[j].point2)
974             editorDraw2dLineMiddle(x1, y1, x1, y1+getscreenvdisp(fzn-fz, zoome), col);
975         }
976 #ifdef YAX_ENABLE
977         {
978             int16_t const nw = yax_getnextwall(i, YAX_CEILING);
979 
980             if (nw >= 0)
981             {
982                 int32_t const odrawlinepat = drawlinepat;
983                 fz2 = getflorzofslope(sectorofwall(nw), wall[nw].x, wall[nw].y);
984                 drawlinepat = 0x11111111;
985                 editorDraw2dLineMiddle(x1, y1, x1, y1+getscreenvdisp(fz2-fz, zoome), col);
986                 drawlinepat = odrawlinepat;
987             }
988         }
989 #endif
990 
991         m32_wallscreenxy[i][0] = halfxdim16+x1;
992         m32_wallscreenxy[i][1] = midydim16+y1;
993     }
994 
995     if (bloodhack ? cstat&1 : wal->cstat&64)  // if hitscan bit set
996     {
997         int32_t const one=(klabs(x2-x1) >= klabs(y2-y1)), no=!one;
998 
999         editorDraw2dLineMiddle(x1+no, y1+one, x2+no, y2+one, col);
1000         editorDraw2dLineMiddle(x1-no, y1-one, x2-no, y2-one, col);
1001     }
1002 
1003     editorDraw2dLineMiddle(x1, y1, x2, y2, col);
1004 
1005     // Draw height indicators at center of walls if requested and if not in
1006     // side-view mode.
1007     // XXX: This does not take sloping into account.
1008     if (showheightindicators && !m32_sideview)
1009     {
1010         int32_t dax, day;
1011         int32_t const k = getangle(x1-x2, y1-y2);
1012 
1013         editorGet2dScreenCoordinates(&dax, &day,
1014             ((wal->x+wall[wal->point2].x)>>1)-posxe,
1015             ((wal->y+wall[wal->point2].y)>>1)-posye, zoome);
1016 
1017         if (wal->nextsector >= 0)
1018         {
1019             int32_t const z1 = sector[sectorofwall(i)].floorz;
1020             int32_t const z2 = sector[wal->nextsector].floorz;
1021 
1022             if (z1 != z2 || showheightindicators == 2)
1023             {
1024                 // Red walls. Show them on equal-height walls ONLY with setting 2.
1025                 int32_t const bb = (z2 < z1);
1026                 int32_t const dx = mulscale11(sintable[(k+1024 + 1024*bb)&2047], min(4096, zoome)) / 2560;
1027                 int32_t const dy = scalescreeny(mulscale11(sintable[(k+512 + 1024*bb)&2047], min(4096, zoome)) / 2560);
1028 
1029                 editorDraw2dLineMiddle(dax, day, dax+dx, day+dy, col);
1030             }
1031         }
1032         else if (showheightindicators == 2)
1033         {
1034             // Show them on white walls ONLY with setting 2.
1035             int32_t const dx = mulscale11(sintable[(k+2048)&2047], min(4096, zoome)) / 2560;
1036             int32_t const dy = scalescreeny(mulscale11(sintable[(k+1536)&2047], min(4096, zoome)) / 2560);
1037 
1038             editorDraw2dLineMiddle(dax, day, dax+dx, day+dy, col);
1039         }
1040     }
1041 
1042     if ((zoome >= 256 && editstatus == 1) || show2dwall[i>>3]&pow2char[i&7])
1043         if ((halfxdim16+x1 >= 2) && (halfxdim16+x1 <= xdim-3) &&
1044             (midydim16+y1 >= 2) && (midydim16+y1 <= ydim16-3))
1045         {
1046             int32_t pointsize = 2;
1047 
1048             col = editorcolors[15];
1049 
1050             if (i == pointhighlight || ((unsigned) pointhighlight < MAXWALLS &&
1051                 (wal->x == wall[pointhighlight].x) && (wal->y == wall[pointhighlight].y)))
1052             {
1053                 col = editorcolors[15] - (M32_THROB>>1);
1054 
1055                 if ((int32_t) totalclock & 16)
1056                     pointsize++;
1057             }
1058 
1059             if (show2dwall[i>>3]&pow2char[i&7])
1060                 col = editorcolors[14] - (M32_THROB>>1);
1061 
1062             if (m32_sideview)
1063             {
1064                 if (wal->nextwall >= 0)
1065                 {
1066                     if (fz < fzn)
1067                         col = editorcolors[7];
1068                     else if (fz == fzn)
1069                         col = editorcolors[4];
1070                 }
1071             }
1072 
1073             editorDraw2dCircle(halfxdim16+x1, midydim16+y1, pointsize, 16384, col);
1074         }
1075 }
1076 
editorGet2dSpriteColor(int32_t spr)1077 int32_t editorGet2dSpriteColor(int32_t spr)
1078 {
1079     int const picnum = sprite[spr].picnum;
1080     int pal = sprite[spr].pal;
1081     int const tilecol = tilecols[picnum];
1082 
1083     if (palookup[pal] == NULL || (tilecol && palookup[pal][tilecol] == 0))
1084         pal = 0;
1085 
1086     if (tilecol) return palookup[pal][tilecol];
1087 
1088     if (!waloff[picnum]) tileLoad(picnum);
1089     if (!waloff[picnum]) return editorcolors[3];
1090 
1091     // Calculate 2D mode tile color.
1092 
1093     uint32_t cols[256];
1094 
1095     Bmemset(cols, 0, sizeof(cols));
1096 
1097     const uint8_t *const texbuf = (const uint8_t *) waloff[picnum];
1098 
1099     for (bssize_t i = 0; i < tilesiz[picnum].x * tilesiz[picnum].y; i++)
1100         cols[texbuf[i]]++;
1101 
1102     unsigned col = 0, cnt = 0;
1103 
1104     for (bssize_t i = 0; i < 240; i++)
1105         if (cols[i] > cnt)
1106             col = i, cnt = cols[i];
1107 
1108     while (col < 240 && curpalette[col+1].r > curpalette[col].r)
1109         col++;
1110 
1111     tilecols[picnum] = col - 4;
1112 
1113     return palookup[pal][tilecols[picnum]];
1114 }
1115 
editorDraw2DBloodMarker(int x,int y,int col)1116 static void editorDraw2DBloodMarker(int x, int y, int col)
1117 {
1118     editorDraw2dCircle(x, y, 4, 16384, col);
1119     editorDraw2dLine(x-2, y-2, x+2, y+2, col);
1120     editorDraw2dLine(x+2, y-2, x-2, y+2, col);
1121 #if 0
1122     plotpixel(x-4, y-1, col);
1123     plotpixel(x-4, y-0, col);
1124     plotpixel(x-4, y+1, col);
1125 
1126     plotpixel(x-3, y-3, col);
1127     plotpixel(x-3, y-2, col);
1128     plotpixel(x-3, y+2, col);
1129     plotpixel(x-3, y+3, col);
1130 
1131     plotpixel(x-2, y-3, col);
1132     plotpixel(x-2, y-2, col);
1133     plotpixel(x-2, y+2, col);
1134     plotpixel(x-2, y+3, col);
1135 
1136     plotpixel(x-1, y-4, col);
1137     plotpixel(x-1, y-1, col);
1138     plotpixel(x-1, y+1, col);
1139     plotpixel(x-1, y+4, col);
1140 
1141     plotpixel(x-0, y-4, col);
1142     plotpixel(x-0, y-0, col);
1143     plotpixel(x-0, y+4, col);
1144 
1145     plotpixel(x+1, y-4, col);
1146     plotpixel(x+1, y-1, col);
1147     plotpixel(x+1, y+1, col);
1148     plotpixel(x+1, y+4, col);
1149 
1150     plotpixel(x+2, y-3, col);
1151     plotpixel(x+2, y-2, col);
1152     plotpixel(x+2, y+2, col);
1153     plotpixel(x+2, y+3, col);
1154 
1155     plotpixel(x+3, y-3, col);
1156     plotpixel(x+3, y-2, col);
1157     plotpixel(x+3, y+2, col);
1158     plotpixel(x+3, y+3, col);
1159 
1160     plotpixel(x+4, y-1, col);
1161     plotpixel(x+4, y-0, col);
1162     plotpixel(x+4, y+1, col);
1163 #endif
1164 }
1165 
editorDraw2dSpriteBloodMarker(int32_t j,int32_t posxe,int32_t posye,int32_t posze,int32_t zoome)1166 static void editorDraw2dSpriteBloodMarker(int32_t j, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome)
1167 {
1168     int32_t x1, y1, x2, y2;
1169     int col;
1170 
1171     const spritetype *const spr = &sprite[j];
1172 
1173     int16_t const angofs = m32_sideview ? m32_sideang : 0;
1174     uint8_t const spritecol = sectorhighlight == spr->owner ? 15 : 14;
1175 
1176     // KEEPINSYNC build.c: drawspritelabel()
1177     if (spr->sectnum<0)
1178         col = editorcolors[4];  // red
1179     else
1180         col = editorcolors[spritecol];
1181 
1182     if (editstatus == 1)
1183     {
1184         if (pointhighlight >= 16384 &&
1185             (j+16384 == pointhighlight ||
1186             (!m32_sideview && (spr->x == sprite[pointhighlight-16384].x &&
1187                 spr->y == sprite[pointhighlight-16384].y))))
1188         {
1189             if (spritecol >= 8 && spritecol <= 15)
1190                 col -= bloodhack ? M32_THROB>>2 : M32_THROB>>1;
1191             else
1192                 col += M32_THROB>>2;
1193         }
1194         else // if (highlightcnt > 0)
1195         {
1196             if (show2dsprite[j>>3]&pow2char[j&7])
1197                 col = editorcolors[14] - (M32_THROB>>1);
1198         }
1199     }
1200 
1201     editorGet2dScreenCoordinates(&x1, &y1, spr->x-posxe, spr->y-posye, zoome);
1202     //   tempint = ((midydim16+y1)*bytesperline)+(halfxdim16+x1)+frameplace;
1203 
1204     if (m32_sideview)
1205         y1 += getscreenvdisp(spr->z-posze, zoome);
1206 
1207     int f = mulscale12(128, zoome);
1208 
1209     if ((halfxdim16+x1 >= -f) && (halfxdim16+x1 < xdim+f) &&
1210         (midydim16+y1 >= -f) && (midydim16+y1 < ydim16+f))
1211     {
1212         if (spr->statnum == 10)
1213         {
1214             switch (spr->type)
1215             {
1216             case 3:
1217             case 4:
1218                 editorDraw2DBloodMarker(halfxdim16+x1, midydim16+y1, col);
1219                 break;
1220 
1221             case 5:
1222             case 6:
1223                 editorDraw2DBloodMarker(halfxdim16+x1, midydim16+y1, col);
1224                 x2 = mulscale11(sintable[(spr->ang+angofs+2560)&2047], zoome) / 768;
1225                 y2 = mulscale11(sintable[(spr->ang+angofs+2048)&2047], zoome) / 768;
1226                 y2 = scalescreeny(y2);
1227 
1228                 editorDraw2dLineMiddle(x1, y1, x1+x2, y1+y2, col);
1229                 break;
1230             }
1231         }
1232         else
1233             editorDraw2DBloodMarker(halfxdim16+x1, midydim16+y1, col);
1234     }
1235 }
1236 
editorDraw2dSprite(int32_t j,int32_t posxe,int32_t posye,int32_t posze,int32_t zoome)1237 static void editorDraw2dSprite(int32_t j, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome)
1238 {
1239     int32_t x1, y1, x2, y2;
1240     int col;
1241 
1242     auto const spr = &sprite[j];
1243     int16_t const blocking = (spr->cstat&1), hitblocking = (spr->cstat&256);
1244     int16_t const flooraligned = (spr->cstat&48) >= 32, wallaligned = (spr->cstat&48) == 16;
1245 
1246     int16_t const angofs = m32_sideview ? m32_sideang : 0;
1247     uint8_t spritecol = spritecol2d[spr->picnum][blocking];
1248 
1249     if (bloodhack)
1250     {
1251         if (spr->statnum == 10 || spr->statnum == 12)
1252         {
1253             editorDraw2dSpriteBloodMarker(j, posxe, posye, posze, zoome);
1254             return;
1255         }
1256         if (spr->cstat & 256)
1257             spritecol = 5;
1258         if (spr->cstat & 0x8000)
1259             spritecol = 8;
1260         if (spr->cstat & 0x2000)
1261             spritecol = 9;
1262         if (spr->cstat & 0x4000)
1263             spritecol = 10;
1264     }
1265 
1266     // KEEPINSYNC build.c: drawspritelabel()
1267     if (spr->sectnum<0)
1268         col = editorcolors[4];  // red
1269     else
1270         col = spritecol ? editorcolors[spritecol] : blocking ? editorcolors[5] : editorGet2dSpriteColor(j);
1271 
1272     if (editstatus == 1)
1273     {
1274         if (pointhighlight >= 16384 &&
1275             (j+16384 == pointhighlight ||
1276             (!m32_sideview && (spr->x == sprite[pointhighlight-16384].x &&
1277                 spr->y == sprite[pointhighlight-16384].y))))
1278         {
1279             if (spritecol >= 8 && spritecol <= 15)
1280                 col -= bloodhack ? M32_THROB>>2 : M32_THROB>>1;
1281             else
1282                 col += M32_THROB>>2;
1283         }
1284         else // if (highlightcnt > 0)
1285         {
1286             if (show2dsprite[j>>3]&pow2char[j&7])
1287                 col = editorcolors[14] - (M32_THROB>>1);
1288         }
1289     }
1290 
1291     editorGet2dScreenCoordinates(&x1, &y1, spr->x-posxe, spr->y-posye, zoome);
1292     //   tempint = ((midydim16+y1)*bytesperline)+(halfxdim16+x1)+frameplace;
1293 
1294     if (m32_sideview)
1295         y1 += getscreenvdisp(spr->z-posze, zoome);
1296 
1297     int f = mulscale12(128, zoome);
1298 
1299     if ((halfxdim16+x1 >= -f) && (halfxdim16+x1 < xdim+f) &&
1300         (midydim16+y1 >= -f) && (midydim16+y1 < ydim16+f))
1301     {
1302         if (zoome > 512 && spr->clipdist > 32)
1303             editorDraw2dCircle(halfxdim16+x1, midydim16+y1, mulscale14(spr->clipdist<<2, zoome), 16384, col);
1304 
1305         editorDraw2dCircle(halfxdim16+x1, midydim16+y1, 4, 16384, col);
1306 
1307         x2 = mulscale11(sintable[(spr->ang+angofs+2560)&2047], zoome) / 768;
1308         y2 = mulscale11(sintable[(spr->ang+angofs+2048)&2047], zoome) / 768;
1309         y2 = scalescreeny(y2);
1310 
1311         editorDraw2dLineMiddle(x1, y1, x1+x2, y1+y2, col);
1312 
1313         if (hitblocking)
1314         {
1315             editorDraw2dLineMiddle(x1, y1+1, x1+x2, y1+y2+1, col);
1316             editorDraw2dLineMiddle(x1, y1-1, x1+x2, y1+y2-1, col);
1317             editorDraw2dLineMiddle(x1-1, y1, x1+x2-1, y1+y2, col);
1318             editorDraw2dLineMiddle(x1+1, y1, x1+x2+1, y1+y2, col);
1319         }
1320 
1321         if (flooraligned)
1322         {
1323             int32_t heinum = spriteGetSlope(j);
1324             int32_t ratio = ksqrt(heinum * heinum + 16777216);
1325             int32_t ratioz = divscale12(heinum, ratio);
1326             int32_t yspan = mulscale6(tilesiz[spr->picnum].y, spr->yrepeat);
1327             int32_t fx = mulscale10(mulscale6(tilesiz[spr->picnum].x, spr->xrepeat), zoome) >> 1;
1328             int32_t fy = divscale12(mulscale10(yspan, zoome) >> 1, ratio);
1329             int32_t fz = getscreenvdisp(mulscale4(yspan, ratioz) >> 1, zoome);
1330             int32_t co[4][3], ii, in;
1331             int32_t sinang = sintable[(spr->ang+angofs+1536)&2047];
1332             int32_t cosang = sintable[(spr->ang+angofs+1024)&2047];
1333             int32_t r, s;
1334 
1335             co[0][0] = co[3][0] = -fx;
1336             co[0][1] = co[1][1] = -fy;
1337             co[0][2] = co[1][2] = -fz;
1338             co[1][0] = co[2][0] = fx;
1339             co[2][1] = co[3][1] = fy;
1340             co[2][2] = co[3][2] = fz;
1341 
1342             for (ii=3; ii>=0; ii--)
1343             {
1344                 r = mulscale14(cosang, co[ii][0]) - mulscale14(sinang, co[ii][1]);
1345                 s = mulscale14(sinang, co[ii][0]) + mulscale14(cosang, co[ii][1]);
1346                 s = scalescreeny(s);
1347                 if (m32_sideview)
1348                     s += co[ii][2];
1349                 co[ii][0] = r;
1350                 co[ii][1] = s;
1351             }
1352             drawlinepat = 0xcfcfcfcf;
1353             for (ii=3; ii>=0; ii--)
1354             {
1355                 in = (ii+1)&3;
1356                 editorDraw2dLineMiddle(x1+co[ii][0], y1-co[ii][1], x1+co[in][0], y1-co[in][1], col);
1357                 if (hitblocking)
1358                 {
1359                     editorDraw2dLineMiddle(x1+co[ii][0], y1-co[ii][1]+1, x1+co[in][0], y1-co[in][1]+1, col);
1360                     editorDraw2dLineMiddle(x1+co[ii][0], y1-co[ii][1]-1, x1+co[in][0], y1-co[in][1]-1, col);
1361                     editorDraw2dLineMiddle(x1+co[ii][0]+1, y1-co[ii][1], x1+co[in][0]+1, y1-co[in][1], col);
1362                     editorDraw2dLineMiddle(x1+co[ii][0]-1, y1-co[ii][1], x1+co[in][0]-1, y1-co[in][1], col);
1363                 }
1364                 editorDraw2dLineMiddle(x1, y1, x1 + co[in][0], y1 - co[in][1], col);
1365             }
1366             drawlinepat = 0xffffffff;
1367         }
1368         else if (wallaligned)
1369         {
1370             int32_t fx = mulscale6(tilesiz[spr->picnum].x, spr->xrepeat);
1371             int32_t one=(((spr->ang+angofs+256)&512) == 0), no=!one;
1372 
1373             x2 = mulscale11(sintable[(spr->ang+angofs+2560)&2047], zoome) / 6144;
1374             y2 = mulscale11(sintable[(spr->ang+angofs+2048)&2047], zoome) / 6144;
1375             y2 = scalescreeny(y2);
1376 
1377             editorDraw2dLineMiddle(x1, y1, x1+x2, y1+y2, col);
1378             if (!(spr->cstat&64))  // not 1-sided
1379             {
1380                 editorDraw2dLineMiddle(x1, y1, x1-x2, y1-y2, col);
1381                 if (hitblocking)
1382                 {
1383                     editorDraw2dLineMiddle(x1-no, y1-one, x1-x2-no, y1-y2-one, col);
1384                     editorDraw2dLineMiddle(x1+no, y1+one, x1-x2+no, y1-y2+one, col);
1385                 }
1386             }
1387 
1388             if (hitblocking)
1389             {
1390                 editorDraw2dLineMiddle(x1-no, y1-one, x1+x2-no, y1+y2-one, col);
1391                 editorDraw2dLineMiddle(x1+no, y1+one, x1+x2+no, y1+y2+one, col);
1392             }
1393 
1394 
1395             x2 = mulscale13(sintable[(spr->ang+angofs+1024)&2047], zoome) * fx / 4096;
1396             y2 = mulscale13(sintable[(spr->ang+angofs+512)&2047], zoome) * fx / 4096;
1397             y2 = scalescreeny(y2);
1398 
1399             editorDraw2dLineMiddle(x1, y1, x1-x2, y1-y2, col);
1400             editorDraw2dLineMiddle(x1, y1, x1+x2, y1+y2, col);
1401 
1402             if (hitblocking)
1403             {
1404                 editorDraw2dLineMiddle(x1+1, y1, x1+x2+1, y1+y2, col);
1405                 editorDraw2dLineMiddle(x1-1, y1, x1-x2-1, y1-y2, col);
1406                 editorDraw2dLineMiddle(x1-1, y1, x1+x2-1, y1+y2, col);
1407                 editorDraw2dLineMiddle(x1+1, y1, x1-x2+1, y1-y2, col);
1408 
1409                 editorDraw2dLineMiddle(x1, y1-1, x1+x2, y1+y2-1, col);
1410                 editorDraw2dLineMiddle(x1, y1+1, x1-x2, y1-y2+1, col);
1411                 editorDraw2dLineMiddle(x1, y1+1, x1+x2, y1+y2+1, col);
1412                 editorDraw2dLineMiddle(x1, y1-1, x1-x2, y1-y2-1, col);
1413             }
1414         }
1415     }
1416 }
1417 
1418 //
1419 // draw2dscreen
1420 //
1421 
1422 static int8_t tempbuf[(MAXWALLS+7)>>3];
1423 
editorDraw2dScreen(const vec3_t * pos,int16_t cursectnum,int16_t ange,int32_t zoome,int16_t gride)1424 void editorDraw2dScreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t zoome, int16_t gride)
1425 {
1426     int32_t i, x1, y1;
1427     int16_t angofs = m32_sideview ? m32_sideang : 0;
1428 
1429     int32_t posxe=pos->x, posye=pos->y, posze=pos->z;
1430     uint8_t *graybitmap = (uint8_t *) tempbuf;
1431     int32_t alwaysshowgray = get_alwaysshowgray();
1432 
1433     if (in3dmode()) return;
1434 
1435     editorSetup2dSideView();
1436 
1437     videoBeginDrawing(); //{{{
1438 
1439 
1440     if (editstatus == 0)
1441     {
1442         //        faketimerhandler();
1443         clear2dscreen();
1444 
1445         //        faketimerhandler();
1446         editorDraw2dGrid(posxe, posye, posze, cursectnum, ange, zoome, gride);
1447     }
1448 
1449     faketimerhandler();
1450 
1451     m32_swcnt = 0;
1452 
1453     if (numgraysects==0)
1454         Bmemset(graybitmap, 0, (numwalls+7)>>3);
1455     else
1456     {
1457         for (i=0; i<numwalls; i++)
1458         {
1459             int32_t j = wall[i].nextwall;
1460             if ((graywallbitmap[i>>3]&pow2char[i&7]) && (j < 0 || (graywallbitmap[j>>3]&pow2char[j&7])))
1461                 graybitmap[i>>3] |= pow2char[i&7];
1462             else
1463                 graybitmap[i>>3] &= ~pow2char[i&7];
1464         }
1465     }
1466 
1467     if (!m32_sideview)
1468     {
1469 #ifndef YAX_ENABLE
1470         for (i=numwalls-1; i>=0; i--)
1471             editorDraw2dWall(i, posxe, posye, posze, zoome, 0);
1472 #else
1473         if (alwaysshowgray)
1474             for (i=numwalls-1; i>=0; i--)
1475                 if (graybitmap[i>>3]&pow2char[i&7])
1476                     editorDraw2dWall(i, posxe, posye, posze, zoome, 1+2);
1477 
1478         for (i=numwalls-1; i>=0; i--)
1479             if ((graybitmap[i>>3]&pow2char[i&7])==0)
1480                 editorDraw2dWall(i, posxe, posye, posze, zoome, 2);
1481 #endif
1482     }
1483     else
1484     {
1485         int32_t j = 0;
1486 
1487         for (i=0; i<numsectors; i++)
1488             for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
1489             {
1490                 m32_wallsprite[m32_swcnt++] = j;
1491                 editorGet2dSideViewDistance(j, i);
1492             }
1493 
1494         // j = sector[numsectors-1].wallptr + sector[numsectors-1].wallnum
1495         for (; j < numwalls; j++)  // new walls ...
1496         {
1497             m32_wallsprite[m32_swcnt++] = j;
1498             editorGet2dSideViewDistance(j, 0);
1499         }
1500     }
1501 
1502     faketimerhandler();
1503 
1504     if (zoome >= 256 || highlightcnt>0)
1505         for (bssize_t j=0; j<MAXSPRITES; j++)
1506             if (sprite[j].statnum<MAXSTATUS)
1507             {
1508                 // if sprite is highlighted, always draw it
1509                 if ((show2dsprite[j>>3]&pow2char[j&7])==0)
1510                 {
1511                     if (!m32_sideview && sprite[j].sectnum >= 0)
1512                         YAX_SKIPSECTOR(sprite[j].sectnum);
1513 
1514                     if (zoome<256)
1515                         continue;
1516                 }
1517 
1518                 if (!m32_sideview)
1519                     editorDraw2dSprite(j, posxe, posye, posze, zoome);
1520                 else
1521                 {
1522                     m32_wallsprite[m32_swcnt++] = MAXWALLS+j;
1523                     editorGet2dSideViewDistance(MAXWALLS+j, -1);
1524                 }
1525             }
1526 
1527     faketimerhandler();
1528 
1529     if (m32_sideview)
1530     {
1531         qsort(m32_wallsprite, m32_swcnt, sizeof(int16_t), &editorCompare2dSideViewPoints);
1532 
1533         for (i=0; i<m32_swcnt; i++)  // shouldn't it go the other way around?
1534         {
1535             int32_t j = m32_wallsprite[i];
1536             if (j<MAXWALLS)
1537             {
1538                 if (alwaysshowgray || !(graybitmap[j>>3]&pow2char[j&7]))
1539                     editorDraw2dWall(j, posxe, posye, posze, zoome, !!(graybitmap[j>>3]&pow2char[j&7]));
1540             }
1541             else
1542             {
1543                 if (!alwaysshowgray && sprite[j-MAXWALLS].sectnum>=0)
1544                     YAX_SKIPSECTOR(sprite[j-MAXWALLS].sectnum);
1545 
1546                 editorDraw2dSprite(j-MAXWALLS, posxe, posye, posze, zoome);
1547             }
1548         }
1549 
1550         faketimerhandler();
1551     }
1552 
1553 #if 0
1554     {
1555         int32_t xx, yy, xx2, yy2;
1556         screencoords(&xx, &yy, -posxe, -posye, zoome);
1557         screencoords(&xx2, &yy2, (m32_viewplane.x)-posxe, (m32_viewplane.y)-posye, zoome);
1558         if (m32_sideview)
1559             yy2 += getscreenvdisp((m32_viewplane.z<<4)-posze, zoome);
1560 
1561         drawcircle16(halfxdim16+xx, midydim16+yy, 2, 16384, editorcolors[4]); //red
1562         drawcircle16(halfxdim16+xx2, midydim16+yy2, 2, 16384, editorcolors[14]); //yellow
1563         drawline16mid(xx, yy, xx2, yy2, editorcolors[15]);
1564     }
1565 #endif
1566 
1567     x1 = mulscale11(sintable[(ange+angofs+2560)&2047], zoome) / 768; //Draw white arrow
1568     y1 = mulscale11(sintable[(ange+angofs+2048)&2047], zoome) / 768;
1569 
1570     i = scalescreeny(x1);
1571     int32_t j = scalescreeny(y1);
1572 
1573     editorDraw2dLineMiddle(x1, j, -x1, -j, editorcolors[15]);
1574     editorDraw2dLineMiddle(x1, j, +y1, -i, editorcolors[15]);
1575     editorDraw2dLineMiddle(x1, j, -y1, +i, editorcolors[15]);
1576 
1577 
1578     videoEndDrawing();   //}}}
1579 }
1580 
1581 //
1582 // setpolymost2dview
1583 //  Sets OpenGL for 2D drawing
1584 //
polymostSet2dView(void)1585 void polymostSet2dView(void)
1586 {
1587 #ifdef USE_OPENGL
1588     if (videoGetRenderMode() < REND_POLYMOST) return;
1589 
1590     glViewport(0, 0, xdim, ydim);
1591 
1592     glMatrixMode(GL_PROJECTION);
1593     glLoadIdentity();
1594     glOrtho(0, xdim, ydim, 0, -1, 1);
1595 
1596     if (videoGetRenderMode() == REND_POLYMER)
1597     {
1598         glMatrixMode(GL_MODELVIEW);
1599         glLoadIdentity();
1600     }
1601 
1602     polymost2d = 1;
1603 
1604     glDisable(GL_DEPTH_TEST);
1605     glDisable(GL_BLEND);
1606 #endif
1607 }
1608