1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: draw.cpp
5 Desc: contains all drawing code
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "draw.hpp"
14 #include "files.hpp"
15 #include "hash.hpp"
16 #include "entity.hpp"
17 #include "player.hpp"
18 #include "editor.hpp"
19 #include "items.hpp"
20
21 /*-------------------------------------------------------------------------------
22
23 getPixel
24
25 gets the value of a pixel at the given x,y location in the given
26 SDL_Surface
27
28 -------------------------------------------------------------------------------*/
29
getPixel(SDL_Surface * surface,int x,int y)30 Uint32 getPixel(SDL_Surface* surface, int x, int y)
31 {
32 int bpp = surface->format->BytesPerPixel;
33 // Here p is the address to the pixel we want to retrieve
34 Uint8* p = (Uint8*)surface->pixels + y * surface->pitch + x * bpp;
35
36 switch (bpp)
37 {
38 case 1:
39 return *p;
40 break;
41
42 case 2:
43 return *(Uint16*)p;
44 break;
45
46 case 3:
47 if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
48 {
49 return p[0] << 16 | p[1] << 8 | p[2];
50 }
51 else
52 {
53 return p[0] | p[1] << 8 | p[2] << 16;
54 }
55 break;
56
57 case 4:
58 return *(Uint32*)p;
59 break;
60
61 default:
62 return 0; /* shouldn't happen, but avoids warnings */
63 }
64 }
65
66 /*-------------------------------------------------------------------------------
67
68 putPixel
69
70 sets the value of a pixel at the given x,y location in the given
71 SDL_Surface
72
73 -------------------------------------------------------------------------------*/
74
putPixel(SDL_Surface * surface,int x,int y,Uint32 pixel)75 void putPixel(SDL_Surface* surface, int x, int y, Uint32 pixel)
76 {
77 int bpp = surface->format->BytesPerPixel;
78 // Here p is the address to the pixel we want to set
79 Uint8* p = (Uint8*)surface->pixels + y * surface->pitch + x * bpp;
80
81 switch (bpp)
82 {
83 case 1:
84 *p = pixel;
85 break;
86
87 case 2:
88 *(Uint16*)p = pixel;
89 break;
90
91 case 3:
92 if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
93 {
94 p[0] = (pixel >> 16) & 0xff;
95 p[1] = (pixel >> 8) & 0xff;
96 p[2] = pixel & 0xff;
97 }
98 else
99 {
100 p[0] = pixel & 0xff;
101 p[1] = (pixel >> 8) & 0xff;
102 p[2] = (pixel >> 16) & 0xff;
103 }
104 break;
105
106 case 4:
107 *(Uint32*)p = pixel;
108 break;
109 }
110 }
111
112 /*-------------------------------------------------------------------------------
113
114 flipSurface
115
116 flips the contents of an SDL_Surface horizontally, vertically, or both
117
118 -------------------------------------------------------------------------------*/
119
flipSurface(SDL_Surface * surface,int flags)120 SDL_Surface* flipSurface( SDL_Surface* surface, int flags )
121 {
122 SDL_Surface* flipped = NULL;
123 Uint32 pixel;
124 int x, rx;
125 int y, ry;
126
127 // prepare surface for flipping
128 flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask );
129 if ( SDL_MUSTLOCK( surface ) )
130 {
131 SDL_LockSurface( surface );
132 }
133 if ( SDL_MUSTLOCK( flipped ) )
134 {
135 SDL_LockSurface( flipped );
136 }
137
138 for ( x = 0, rx = flipped->w - 1; x < flipped->w; x++, rx-- )
139 {
140 for ( y = 0, ry = flipped->h - 1; y < flipped->h; y++, ry-- )
141 {
142 pixel = getPixel( surface, x, y );
143
144 // copy pixel
145 if ( ( flags & FLIP_VERTICAL ) && ( flags & FLIP_HORIZONTAL ) )
146 {
147 putPixel( flipped, rx, ry, pixel );
148 }
149 else if ( flags & FLIP_HORIZONTAL )
150 {
151 putPixel( flipped, rx, y, pixel );
152 }
153 else if ( flags & FLIP_VERTICAL )
154 {
155 putPixel( flipped, x, ry, pixel );
156 }
157 }
158 }
159
160 // restore image
161 if ( SDL_MUSTLOCK( surface ) )
162 {
163 SDL_UnlockSurface( surface );
164 }
165 if ( SDL_MUSTLOCK( flipped ) )
166 {
167 SDL_UnlockSurface( flipped );
168 }
169
170 return flipped;
171 }
172
173 /*-------------------------------------------------------------------------------
174
175 drawCircle
176
177 draws a circle in either an opengl or SDL context
178
179 -------------------------------------------------------------------------------*/
180
drawCircle(int x,int y,real_t radius,Uint32 color,Uint8 alpha)181 void drawCircle( int x, int y, real_t radius, Uint32 color, Uint8 alpha )
182 {
183 drawArc(x, y, radius, 0, 360, color, alpha);
184 }
185
186 /*-------------------------------------------------------------------------------
187
188 drawArc
189
190 draws an arc in either an opengl or SDL context
191
192 -------------------------------------------------------------------------------*/
193
drawArc(int x,int y,real_t radius,real_t angle1,real_t angle2,Uint32 color,Uint8 alpha)194 void drawArc( int x, int y, real_t radius, real_t angle1, real_t angle2, Uint32 color, Uint8 alpha )
195 {
196 int c;
197
198 // update projection
199 glDisable(GL_DEPTH_TEST);
200 glDisable(GL_LIGHTING);
201 glMatrixMode(GL_PROJECTION);
202 glViewport(0, 0, xres, yres);
203 glLoadIdentity();
204 glOrtho(0, xres, 0, yres, -1, 1);
205 glMatrixMode(GL_MODELVIEW);
206 glEnable(GL_BLEND);
207
208 // set line width
209 GLint lineWidth;
210 glGetIntegerv(GL_LINE_WIDTH, &lineWidth);
211 glLineWidth(2);
212
213 // draw line
214 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, alpha / 255.f);
215 glBindTexture(GL_TEXTURE_2D, 0);
216 glEnable(GL_LINE_SMOOTH);
217 glBegin(GL_LINE_STRIP);
218 for ( c = angle1; c <= angle2; c++)
219 {
220 float degInRad = c * PI / 180.f;
221 glVertex2f(x + ceil(cos(degInRad)*radius) + 1, yres - (y + ceil(sin(degInRad)*radius)));
222 }
223 glEnd();
224 glDisable(GL_LINE_SMOOTH);
225
226 // reset line width
227 glLineWidth(lineWidth);
228 }
229
230 /*-------------------------------------------------------------------------------
231
232 drawArcInvertedY, reversing the angle of direction in the y coordinate.
233
234 draws an arc in either an opengl or SDL context
235
236 -------------------------------------------------------------------------------*/
237
drawArcInvertedY(int x,int y,real_t radius,real_t angle1,real_t angle2,Uint32 color,Uint8 alpha)238 void drawArcInvertedY(int x, int y, real_t radius, real_t angle1, real_t angle2, Uint32 color, Uint8 alpha)
239 {
240 int c;
241
242 // update projection
243 glDisable(GL_DEPTH_TEST);
244 glDisable(GL_LIGHTING);
245 glMatrixMode(GL_PROJECTION);
246 glViewport(0, 0, xres, yres);
247 glLoadIdentity();
248 glOrtho(0, xres, 0, yres, -1, 1);
249 glMatrixMode(GL_MODELVIEW);
250 glEnable(GL_BLEND);
251
252 // set line width
253 GLint lineWidth;
254 glGetIntegerv(GL_LINE_WIDTH, &lineWidth);
255 glLineWidth(2);
256
257 // draw line
258 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, alpha / 255.f);
259 glBindTexture(GL_TEXTURE_2D, 0);
260 glEnable(GL_LINE_SMOOTH);
261 glBegin(GL_LINE_STRIP);
262 for ( c = angle1; c <= angle2; c++ )
263 {
264 float degInRad = c * PI / 180.f;
265 glVertex2f(x + ceil(cos(degInRad)*radius) + 1, yres - (y - ceil(sin(degInRad)*radius)));
266 }
267 glEnd();
268 glDisable(GL_LINE_SMOOTH);
269
270 // reset line width
271 glLineWidth(lineWidth);
272 }
273
274 /*-------------------------------------------------------------------------------
275
276 drawLine
277
278 draws a line in either an opengl or SDL context
279
280 -------------------------------------------------------------------------------*/
281
drawLine(int x1,int y1,int x2,int y2,Uint32 color,Uint8 alpha)282 void drawLine( int x1, int y1, int x2, int y2, Uint32 color, Uint8 alpha )
283 {
284 // update projection
285 glDisable(GL_DEPTH_TEST);
286 glDisable(GL_LIGHTING);
287 glMatrixMode(GL_PROJECTION);
288 glViewport(0, 0, xres, yres);
289 glLoadIdentity();
290 glOrtho(0, xres, 0, yres, -1, 1);
291 glMatrixMode(GL_MODELVIEW);
292 glEnable(GL_BLEND);
293
294 // set line width
295 GLint lineWidth;
296 glGetIntegerv(GL_LINE_WIDTH, &lineWidth);
297 glLineWidth(2);
298
299 // draw line
300 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, alpha / 255.f);
301 glBindTexture(GL_TEXTURE_2D, 0);
302 glEnable(GL_LINE_SMOOTH);
303 glBegin(GL_LINES);
304 glVertex2f(x1 + 1, yres - y1);
305 glVertex2f(x2 + 1, yres - y2);
306 glEnd();
307 glDisable(GL_LINE_SMOOTH);
308
309 // reset line width
310 glLineWidth(lineWidth);
311 }
312
313 /*-------------------------------------------------------------------------------
314
315 drawRect
316
317 draws a rectangle in either an opengl or SDL context
318
319 -------------------------------------------------------------------------------*/
320
drawRect(SDL_Rect * src,Uint32 color,Uint8 alpha)321 int drawRect( SDL_Rect* src, Uint32 color, Uint8 alpha )
322 {
323 SDL_Rect secondsrc;
324
325 // update projection
326 glDisable(GL_DEPTH_TEST);
327 glDisable(GL_LIGHTING);
328 glMatrixMode(GL_PROJECTION);
329 glViewport(0, 0, xres, yres);
330 glLoadIdentity();
331 glOrtho(0, xres, 0, yres, -1, 1);
332 glMatrixMode(GL_MODELVIEW);
333 glEnable(GL_BLEND);
334
335 // for the use of the whole screen
336 if ( src == NULL )
337 {
338 secondsrc.x = 0;
339 secondsrc.y = 0;
340 secondsrc.w = xres;
341 secondsrc.h = yres;
342 src = &secondsrc;
343 }
344
345 // draw quad
346 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, alpha / 255.f);
347 glBindTexture(GL_TEXTURE_2D, 0);
348 glBegin(GL_QUADS);
349 glVertex2f(src->x, yres - src->y);
350 glVertex2f(src->x, yres - src->y - src->h);
351 glVertex2f(src->x + src->w, yres - src->y - src->h);
352 glVertex2f(src->x + src->w, yres - src->y);
353 glEnd();
354 return 0;
355 }
356
357
358 /*-------------------------------------------------------------------------------
359
360 drawBox
361
362 draws the border of a rectangle
363
364 -------------------------------------------------------------------------------*/
drawBox(SDL_Rect * src,Uint32 color,Uint8 alpha)365 int drawBox(SDL_Rect* src, Uint32 color, Uint8 alpha)
366 {
367 drawLine(src->x, src->y, src->x + src->w, src->y, color, alpha); //Top.
368 drawLine(src->x, src->y, src->x, src->y + src->h, color, alpha); //Left.
369 drawLine(src->x + src->w, src->y, src->x + src->w, src->y + src->h, color, alpha); //Right.
370 drawLine(src->x, src->y + src->h, src->x + src->w, src->y + src->h, color, alpha); //Bottom.
371 return 0;
372 }
373
374 /*-------------------------------------------------------------------------------
375
376 drawGear
377
378 draws a gear (used for turning wheel splash)
379
380 -------------------------------------------------------------------------------*/
381
drawGear(Sint16 x,Sint16 y,real_t size,Sint32 rotation)382 void drawGear(Sint16 x, Sint16 y, real_t size, Sint32 rotation)
383 {
384 Uint32 color;
385 int c;
386 Sint16 x1, y1, x2, y2;
387
388 color = SDL_MapRGB(mainsurface->format, 255, 127, 0);
389 for ( c = 0; c < 6; c++ )
390 {
391 drawArc(x, y, size, 0 + c * 60 + rotation, 30 + c * 60 + rotation, color, 255);
392 drawArc(x, y, (int)ceil(size * 1.33), 30 + c * 60 + 4 + rotation, 60 + c * 60 - 4 + rotation, color, 255);
393 x1 = ceil(size * cos((30 + c * 60 + rotation) * (PI / 180))) + x;
394 y1 = ceil(size * sin((30 + c * 60 + rotation) * (PI / 180))) + y;
395 x2 = ceil(size * cos((30 + c * 60 + 4 + rotation) * (PI / 180)) * 1.33) + x;
396 y2 = ceil(size * sin((30 + c * 60 + 4 + rotation) * (PI / 180)) * 1.33) + y;
397 drawLine(x1, y1, x2, y2, color, 255);
398 x1 = ceil(size * cos((60 + c * 60 + rotation) * (PI / 180))) + x;
399 y1 = ceil(size * sin((60 + c * 60 + rotation) * (PI / 180))) + y;
400 x2 = ceil(size * cos((60 + c * 60 - 4 + rotation) * (PI / 180)) * 1.33) + x;
401 y2 = ceil(size * sin((60 + c * 60 - 4 + rotation) * (PI / 180)) * 1.33) + y;
402 drawLine(x1, y1, x2, y2, color, 255);
403 }
404 color = SDL_MapRGBA(mainsurface->format, 191, 63, 0, 255);
405 drawCircle(x, y, size * .66, color, 255);
406 color = SDL_MapRGBA(mainsurface->format, 127, 0, 0, 255);
407 drawCircle(x, y, size * .25, color, 255);
408 }
409
410 /*-------------------------------------------------------------------------------
411
412 drawImageRotatedAlpha
413
414 blits an image in either an opengl or SDL context, rotating the image
415 relative to the screen and taking an alpha value
416
417 -------------------------------------------------------------------------------*/
418
drawImageRotatedAlpha(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos,real_t angle,Uint8 alpha)419 void drawImageRotatedAlpha( SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos, real_t angle, Uint8 alpha )
420 {
421 SDL_Rect secondsrc;
422
423 // update projection
424 glPushMatrix();
425 glDisable(GL_DEPTH_TEST);
426 glMatrixMode(GL_PROJECTION);
427 glViewport(0, 0, xres, yres);
428 glLoadIdentity();
429 glOrtho(0, xres, 0, yres, -1, 1);
430 glMatrixMode(GL_MODELVIEW);
431 glEnable(GL_BLEND);
432 glTranslatef(pos->x, yres - pos->y, 0);
433 glRotatef(-angle * 180 / PI, 0.f, 0.f, 1.f);
434
435 // for the use of a whole image
436 if ( src == NULL )
437 {
438 secondsrc.x = 0;
439 secondsrc.y = 0;
440 secondsrc.w = image->w;
441 secondsrc.h = image->h;
442 src = &secondsrc;
443 }
444
445 // draw a textured quad
446 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
447 glColor4f(1, 1, 1, alpha / 255.1);
448 glBegin(GL_QUADS);
449 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * ((real_t)src->y / image->h));
450 glVertex2f(-src->w / 2, src->h / 2);
451 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
452 glVertex2f(-src->w / 2, -src->h / 2);
453 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
454 glVertex2f(src->w / 2, -src->h / 2);
455 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * ((real_t)src->y / image->h));
456 glVertex2f(src->w / 2, src->h / 2);
457 glEnd();
458 glPopMatrix();
459 glEnable(GL_DEPTH_TEST);
460 }
461
462 /*-------------------------------------------------------------------------------
463
464 drawImageColor
465
466 blits an image in either an opengl or SDL context while colorizing it
467
468 -------------------------------------------------------------------------------*/
469
drawImageColor(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos,Uint32 color)470 void drawImageColor( SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos, Uint32 color )
471 {
472 SDL_Rect secondsrc;
473
474 // update projection
475 glPushMatrix();
476 glDisable(GL_DEPTH_TEST);
477 glMatrixMode(GL_PROJECTION);
478 glViewport(0, 0, xres, yres);
479 glLoadIdentity();
480 glOrtho(0, xres, 0, yres, -1, 1);
481 glMatrixMode(GL_MODELVIEW);
482 glEnable(GL_BLEND);
483
484 // for the use of a whole image
485 if ( src == NULL )
486 {
487 secondsrc.x = 0;
488 secondsrc.y = 0;
489 secondsrc.w = image->w;
490 secondsrc.h = image->h;
491 src = &secondsrc;
492 }
493
494 // draw a textured quad
495 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
496 real_t r = ((Uint8)(color >> mainsurface->format->Rshift)) / 255.f;
497 real_t g = ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f;
498 real_t b = ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f;
499 real_t a = ((Uint8)(color >> mainsurface->format->Ashift)) / 255.f;
500 glColor4f(r, g, b, a);
501 glPushMatrix();
502 glBegin(GL_QUADS);
503 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * ((real_t)src->y / image->h));
504 glVertex2f(pos->x, yres - pos->y);
505 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
506 glVertex2f(pos->x, yres - pos->y - src->h);
507 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
508 glVertex2f(pos->x + src->w, yres - pos->y - src->h);
509 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * ((real_t)src->y / image->h));
510 glVertex2f(pos->x + src->w, yres - pos->y);
511 glEnd();
512 glPopMatrix();
513 glEnable(GL_DEPTH_TEST);
514 }
515
516 /*-------------------------------------------------------------------------------
517
518 drawImageAlpha
519
520 blits an image in either an opengl or SDL context, taking an alpha value
521
522 -------------------------------------------------------------------------------*/
523
drawImageAlpha(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos,Uint8 alpha)524 void drawImageAlpha( SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos, Uint8 alpha )
525 {
526 SDL_Rect secondsrc;
527
528 // update projection
529 glPushMatrix();
530 glDisable(GL_DEPTH_TEST);
531 glMatrixMode(GL_PROJECTION);
532 glViewport(0, 0, xres, yres);
533 glLoadIdentity();
534 glOrtho(0, xres, 0, yres, -1, 1);
535 glMatrixMode(GL_MODELVIEW);
536 glEnable(GL_BLEND);
537
538 // for the use of a whole image
539 if ( src == NULL )
540 {
541 secondsrc.x = 0;
542 secondsrc.y = 0;
543 secondsrc.w = image->w;
544 secondsrc.h = image->h;
545 src = &secondsrc;
546 }
547
548 // draw a textured quad
549 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
550 glColor4f(1, 1, 1, alpha / 255.1);
551 glPushMatrix();
552 glBegin(GL_QUADS);
553 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * ((real_t)src->y / image->h));
554 glVertex2f(pos->x, yres - pos->y);
555 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
556 glVertex2f(pos->x, yres - pos->y - src->h);
557 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
558 glVertex2f(pos->x + src->w, yres - pos->y - src->h);
559 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * ((real_t)src->y / image->h));
560 glVertex2f(pos->x + src->w, yres - pos->y);
561 glEnd();
562 glPopMatrix();
563 glEnable(GL_DEPTH_TEST);
564 }
565
566 /*-------------------------------------------------------------------------------
567
568 drawImage
569
570 blits an image in either an opengl or SDL context
571
572 -------------------------------------------------------------------------------*/
573
drawImage(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos)574 void drawImage( SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos )
575 {
576 SDL_Rect secondsrc;
577
578 // update projection
579 glPushMatrix();
580 glDisable(GL_DEPTH_TEST);
581 glMatrixMode(GL_PROJECTION);
582 glViewport(0, 0, xres, yres);
583 glLoadIdentity();
584 glOrtho(0, xres, 0, yres, -1, 1);
585 glMatrixMode(GL_MODELVIEW);
586 glEnable(GL_BLEND);
587
588 // for the use of a whole image
589 if ( src == NULL )
590 {
591 secondsrc.x = 0;
592 secondsrc.y = 0;
593 secondsrc.w = image->w;
594 secondsrc.h = image->h;
595 src = &secondsrc;
596 }
597
598 // draw a textured quad
599 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
600 glColor4f(1, 1, 1, 1);
601 glPushMatrix();
602 glBegin(GL_QUADS);
603 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * ((real_t)src->y / image->h));
604 glVertex2f(pos->x, yres - pos->y);
605 glTexCoord2f(1.0 * ((real_t)src->x / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
606 glVertex2f(pos->x, yres - pos->y - src->h);
607 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * (((real_t)src->y + src->h) / image->h));
608 glVertex2f(pos->x + src->w, yres - pos->y - src->h);
609 glTexCoord2f(1.0 * (((real_t)src->x + src->w) / image->w), 1.0 * ((real_t)src->y / image->h));
610 glVertex2f(pos->x + src->w, yres - pos->y);
611 glEnd();
612 glPopMatrix();
613 glEnable(GL_DEPTH_TEST);
614 }
615
616 /*-------------------------------------------------------------------------------
617
618 drawImageRing
619
620 blits an image in either an opengl or SDL context into a 2d ring.
621
622 -------------------------------------------------------------------------------*/
623
drawImageRing(SDL_Surface * image,SDL_Rect * src,int radius,int thickness,int segments,real_t angStart,real_t angEnd,Uint8 alpha)624 void drawImageRing(SDL_Surface* image, SDL_Rect* src, int radius, int thickness, int segments, real_t angStart, real_t angEnd, Uint8 alpha)
625 {
626 SDL_Rect secondsrc;
627
628 // update projection
629 glPushMatrix();
630 glDisable(GL_DEPTH_TEST);
631 glMatrixMode(GL_PROJECTION);
632 glViewport(0, 0, xres, yres);
633 glLoadIdentity();
634 glOrtho(0, xres, 0, yres, -1, 1);
635 glMatrixMode(GL_MODELVIEW);
636 glEnable(GL_BLEND);
637
638 // for the use of a whole image
639 if ( src == NULL )
640 {
641 secondsrc.x = 0;
642 secondsrc.y = 0;
643 secondsrc.w = image->w;
644 secondsrc.h = image->h;
645 src = &secondsrc;
646 }
647
648 // draw a textured quad
649 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
650 glColor4f(1, 1, 1, alpha / 255.f);
651 glPushMatrix();
652
653 double s;
654 real_t arcAngle = angStart;
655 int first = segments / 2;
656 real_t distance = std::round((angEnd - angStart) * segments / (2 * PI));
657 for ( int i = 0; i < first; ++i )
658 {
659 glBegin(GL_QUAD_STRIP);
660 for ( int j = 0; j <= static_cast<int>(distance); ++j )
661 {
662 s = i % first + 0.01;
663 arcAngle = ((j % segments) * 2 * PI / segments) + angStart; // angle of the line.
664
665 real_t arcx1 = (radius + thickness * cos(s * 2 * PI / first)) * cos(arcAngle);
666 real_t arcy1 = (radius + thickness * cos(s * 2 * PI / first)) * sin(arcAngle);
667
668 s = (i + 1) % first + 0.01;
669 real_t arcx2 = (radius + thickness * cos(s * 2 * PI / first)) * cos(arcAngle);
670 real_t arcy2 = (radius + thickness * cos(s * 2 * PI / first)) * sin(arcAngle);
671 //glTexCoord2f(1.f, 0.f);
672 glVertex2f(xres / 2 + arcx1, yres / 2 + arcy1);
673 //glTexCoord2f(0.f, 1.f);
674 glVertex2f(xres / 2 + arcx2, yres / 2 + arcy2);
675 //s = i % first + 0.01;
676 //arcAngle = (((j + 1) % segments) * 2 * PI / segments) + angStart; // angle of the line.
677 //real_t arcx3 = (radius + thickness * cos(s * 2 * PI / first)) * cos(arcAngle);
678 //real_t arcy3 = (radius + thickness * cos(s * 2 * PI / first)) * sin(arcAngle);
679
680 //s = (i + 1) % first + 0.01;
681 //real_t arcx4 = (radius + thickness * cos(s * 2 * PI / first)) * cos(arcAngle);
682 //real_t arcy4 = (radius + thickness * cos(s * 2 * PI / first)) * sin(arcAngle);
683
684 //std::vector<std::pair<real_t, real_t>> xycoords;
685 //xycoords.push_back(std::make_pair(arcx1, arcy1));
686 //xycoords.push_back(std::make_pair(arcx2, arcy2));
687 //xycoords.push_back(std::make_pair(arcx3, arcy3));
688 //xycoords.push_back(std::make_pair(arcx4, arcy4));
689 //std::sort(xycoords.begin(), xycoords.end());
690 //if ( xycoords.at(2).second < xycoords.at(3).second )
691 //{
692 // glTexCoord2f(1.f, 0.f);
693 // glVertex2f(xres / 2 + xycoords.at(2).first, yres / 2 + xycoords.at(2).second); // lower right.
694 // glTexCoord2f(1.f, 1.f);
695 // glVertex2f(xres / 2 + xycoords.at(3).first, yres / 2 + xycoords.at(3).second); // upper right.
696 //}
697 //else
698 //{
699 // glTexCoord2f(1.f, 0.f);
700 // glVertex2f(xres / 2 + xycoords.at(3).first, yres / 2 + xycoords.at(3).second); // lower right.
701 // glTexCoord2f(1.f, 1.f);
702 // glVertex2f(xres / 2 + xycoords.at(2).first, yres / 2 + xycoords.at(2).second); // upper right.
703 //}
704 //if ( xycoords.at(0).second < xycoords.at(1).second )
705 //{
706 // glTexCoord2f(0.f, 0.f);
707 // glVertex2f(xres / 2 + xycoords.at(0).first, yres / 2 + xycoords.at(0).second); // lower left.
708 // glTexCoord2f(0.f, 1.f);
709 // glVertex2f(xres / 2 + xycoords.at(1).first, yres / 2 + xycoords.at(1).second); // upper left.
710 //}
711 //else
712 //{
713 // glTexCoord2f(0.f, 0.f);
714 // glVertex2f(xres / 2 + xycoords.at(1).first, yres / 2 + xycoords.at(1).second); // lower left.
715 // glTexCoord2f(0.f, 1.f);
716 // glVertex2f(xres / 2 + xycoords.at(0).first, yres / 2 + xycoords.at(0).second); // upper left.
717 //}
718
719
720 //glVertex2f(xres / 2 + arcx3, yres / 2 + arcy3);
721 //glVertex2f(xres / 2 + arcx4, yres / 2 + arcy4);
722 }
723 glEnd();
724 }
725 glPopMatrix();
726 // debug lines
727 /*real_t x1 = xres / 2 + 300 * cos(angStart);
728 real_t y1 = yres / 2 - 300 * sin(angStart);
729 real_t x2 = xres / 2 + 300 * cos(angEnd);
730 real_t y2 = yres / 2 - 300 * sin(angEnd);
731 drawLine(xres / 2, yres / 2, x1, y1, 0xFFFFFFFF, 255);
732 drawLine(xres / 2, yres / 2, x2, y2, 0xFFFFFFFF, 255);*/
733 glEnable(GL_DEPTH_TEST);
734 }
735
736 /*-------------------------------------------------------------------------------
737
738 drawImageScaled
739
740 blits an image in either an opengl or SDL context, scaling it
741
742 -------------------------------------------------------------------------------*/
743
drawImageScaled(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos)744 void drawImageScaled( SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos )
745 {
746 SDL_Rect secondsrc;
747
748 if ( !image )
749 {
750 return;
751 }
752
753 // update projection
754 glPushMatrix();
755 glDisable(GL_DEPTH_TEST);
756 glMatrixMode(GL_PROJECTION);
757 glViewport(0, 0, xres, yres);
758 glLoadIdentity();
759 glOrtho(0, xres, 0, yres, -1, 1);
760 glMatrixMode(GL_MODELVIEW);
761 glEnable(GL_BLEND);
762
763 // for the use of a whole image
764 if ( src == NULL )
765 {
766 secondsrc.x = 0;
767 secondsrc.y = 0;
768 secondsrc.w = image->w;
769 secondsrc.h = image->h;
770 src = &secondsrc;
771 }
772
773 // draw a textured quad
774 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
775 glColor4f(1, 1, 1, 1);
776 glPushMatrix();
777 glBegin(GL_QUADS);
778 glTexCoord2f(0.f, 0.f);
779 glVertex2f(pos->x, yres - pos->y);
780 glTexCoord2f(0.f, 1.f);
781 glVertex2f(pos->x, yres - pos->y - pos->h);
782 glTexCoord2f(1.f, 1.f);
783 glVertex2f(pos->x + pos->w, yres - pos->y - pos->h);
784 glTexCoord2f(1.f, 0.f);
785 glVertex2f(pos->x + pos->w, yres - pos->y);
786 glEnd();
787 glPopMatrix();
788 glEnable(GL_DEPTH_TEST);
789 }
790
791 /*-------------------------------------------------------------------------------
792
793 drawImageScaledPartial
794
795 blits an image in either an opengl or SDL context, scaling it
796
797 -------------------------------------------------------------------------------*/
798
drawImageScaledPartial(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos,float percentY)799 void drawImageScaledPartial(SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos, float percentY)
800 {
801 SDL_Rect secondsrc;
802
803 if ( !image )
804 {
805 return;
806 }
807
808 // update projection
809 glPushMatrix();
810 glDisable(GL_DEPTH_TEST);
811 glMatrixMode(GL_PROJECTION);
812 glViewport(0, 0, xres, yres);
813 glLoadIdentity();
814 glOrtho(0, xres, 0, yres, -1, 1);
815 glMatrixMode(GL_MODELVIEW);
816 glEnable(GL_BLEND);
817
818 // for the use of a whole image
819 if ( src == NULL )
820 {
821 secondsrc.x = 0;
822 secondsrc.y = 0;
823 secondsrc.w = image->w;
824 secondsrc.h = image->h;
825 src = &secondsrc;
826 }
827
828 // draw a textured quad
829 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
830 glColor4f(1, 1, 1, 1);
831 glPushMatrix();
832 glBegin(GL_QUADS);
833 glTexCoord2f(0.f, 1.f - 1.f * percentY); // top left.
834 glVertex2f(pos->x, yres - pos->y - pos->h + pos->h * percentY);
835
836 glTexCoord2f(0.f, 1.f); // bottom left
837 glVertex2f(pos->x, yres - pos->y - pos->h);
838
839 glTexCoord2f(1.f, 1.f); // bottom right
840 glVertex2f(pos->x + pos->w, yres - pos->y - pos->h);
841
842 glTexCoord2f(1.f, 1.f - 1.f * percentY); // top right
843 glVertex2f(pos->x + pos->w, yres - pos->y - pos->h + pos->h * percentY);
844 glEnd();
845 glPopMatrix();
846 glEnable(GL_DEPTH_TEST);
847
848 // debug corners
849 //Uint32 color = SDL_MapRGB(mainsurface->format, 64, 255, 64); // green
850 //drawCircle(pos->x, pos->y + (pos->h - (pos->h * percentY)), 5, color, 255);
851 //color = SDL_MapRGB(mainsurface->format, 204, 121, 167); // pink
852 //drawCircle(pos->x, pos->y + pos->h, 5, color, 255);
853 //color = SDL_MapRGB(mainsurface->format, 86, 180, 233); // sky blue
854 //drawCircle(pos->x + pos->w, pos->y + pos->h, 5, color, 255);
855 //color = SDL_MapRGB(mainsurface->format, 240, 228, 66); // yellow
856 //drawCircle(pos->x + pos->w, pos->y + (pos->h - (pos->h * percentY)), 5, color, 255);
857 }
858
859 /*-------------------------------------------------------------------------------
860
861 drawImageScaledColor
862
863 blits an image in either an opengl or SDL context while colorizing and scaling it
864
865 -------------------------------------------------------------------------------*/
866
drawImageScaledColor(SDL_Surface * image,SDL_Rect * src,SDL_Rect * pos,Uint32 color)867 void drawImageScaledColor(SDL_Surface* image, SDL_Rect* src, SDL_Rect* pos, Uint32 color)
868 {
869 SDL_Rect secondsrc;
870
871 // update projection
872 glPushMatrix();
873 glDisable(GL_DEPTH_TEST);
874 glMatrixMode(GL_PROJECTION);
875 glViewport(0, 0, xres, yres);
876 glLoadIdentity();
877 glOrtho(0, xres, 0, yres, -1, 1);
878 glMatrixMode(GL_MODELVIEW);
879 glEnable(GL_BLEND);
880
881 // for the use of a whole image
882 if ( src == NULL )
883 {
884 secondsrc.x = 0;
885 secondsrc.y = 0;
886 secondsrc.w = image->w;
887 secondsrc.h = image->h;
888 src = &secondsrc;
889 }
890
891 // draw a textured quad
892 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
893 real_t r = ((Uint8)(color >> mainsurface->format->Rshift)) / 255.f;
894 real_t g = ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f;
895 real_t b = ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f;
896 real_t a = ((Uint8)(color >> mainsurface->format->Ashift)) / 255.f;
897 glColor4f(r, g, b, a);
898 glPushMatrix();
899 glBegin(GL_QUADS);
900 glTexCoord2f(0.f, 0.f);
901 glVertex2f(pos->x, yres - pos->y);
902 glTexCoord2f(0.f, 1.f);
903 glVertex2f(pos->x, yres - pos->y - pos->h);
904 glTexCoord2f(1.f, 1.f);
905 glVertex2f(pos->x + pos->w, yres - pos->y - pos->h);
906 glTexCoord2f(1.f, 0.f);
907 glVertex2f(pos->x + pos->w, yres - pos->y);
908 glEnd();
909 glPopMatrix();
910 glEnable(GL_DEPTH_TEST);
911 }
912
913 /*-------------------------------------------------------------------------------
914
915 scaleSurface
916
917 Scales an SDL_Surface to the given width and height.
918
919 -------------------------------------------------------------------------------*/
920
scaleSurface(SDL_Surface * Surface,Uint16 Width,Uint16 Height)921 SDL_Surface* scaleSurface(SDL_Surface* Surface, Uint16 Width, Uint16 Height)
922 {
923 Sint32 x, y, o_x, o_y;
924
925 if (!Surface || !Width || !Height)
926 {
927 return NULL;
928 }
929
930 SDL_Surface* _ret = SDL_CreateRGBSurface(Surface->flags, Width, Height, Surface->format->BitsPerPixel, Surface->format->Rmask, Surface->format->Gmask, Surface->format->Bmask, Surface->format->Amask);
931
932 real_t _stretch_factor_x = (real_t)Width / (real_t)Surface->w;
933 real_t _stretch_factor_y = (real_t)Height / (real_t)Surface->h;
934
935 for (y = 0; y < Surface->h; y++)
936 for (x = 0; x < Surface->w; x++)
937 for (o_y = 0; o_y < _stretch_factor_y; ++o_y)
938 for (o_x = 0; o_x < _stretch_factor_x; ++o_x)
939 {
940 putPixel(_ret, (Sint32)(_stretch_factor_x * x) + o_x, (Sint32)(_stretch_factor_y * y) + o_y, getPixel(Surface, x, y));
941 }
942
943 free(Surface);
944 return _ret;
945 }
946
947 /*-------------------------------------------------------------------------------
948
949 drawImageFancy
950
951 blits an image in either an opengl or SDL context, while coloring,
952 rotating, and scaling it
953
954 -------------------------------------------------------------------------------*/
955
drawImageFancy(SDL_Surface * image,Uint32 color,real_t angle,SDL_Rect * src,SDL_Rect * pos)956 void drawImageFancy( SDL_Surface* image, Uint32 color, real_t angle, SDL_Rect* src, SDL_Rect* pos )
957 {
958 SDL_Rect secondsrc;
959
960 if ( !image )
961 {
962 return;
963 }
964
965 // update projection
966 glPushMatrix();
967 glDisable(GL_DEPTH_TEST);
968 glMatrixMode(GL_PROJECTION);
969 glViewport(0, 0, xres, yres);
970 glLoadIdentity();
971 glOrtho(0, xres, 0, yres, -1, 1);
972 glMatrixMode(GL_MODELVIEW);
973 glEnable(GL_BLEND);
974 glTranslatef(pos->x, yres - pos->y, 0);
975 glRotatef(-angle * 180 / PI, 0.f, 0.f, 1.f);
976
977 // for the use of a whole image
978 if ( src == NULL )
979 {
980 secondsrc.x = 0;
981 secondsrc.y = 0;
982 secondsrc.w = image->w;
983 secondsrc.h = image->h;
984 src = &secondsrc;
985 }
986
987 // draw a textured quad
988 glBindTexture(GL_TEXTURE_2D, texid[image->refcount]);
989 real_t r = ((Uint8)(color >> mainsurface->format->Rshift)) / 255.f;
990 real_t g = ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f;
991 real_t b = ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f;
992 real_t a = ((Uint8)(color >> mainsurface->format->Ashift)) / 255.f;
993 glColor4f(r, g, b, a);
994 glPushMatrix();
995 glBegin(GL_QUADS);
996 glTexCoord2f(((real_t)src->x) / ((real_t)image->w), ((real_t)src->y) / ((real_t)image->h));
997 glVertex2f(0, 0);
998 glTexCoord2f(((real_t)src->x) / ((real_t)image->w), ((real_t)(src->y + src->h)) / ((real_t)image->h));
999 glVertex2f(0, -pos->h);
1000 glTexCoord2f(((real_t)(src->x + src->w)) / ((real_t)image->w), ((real_t)(src->y + src->h)) / ((real_t)image->h));
1001 glVertex2f(pos->w, -pos->h);
1002 glTexCoord2f(((real_t)(src->x + src->w)) / ((real_t)image->w), ((real_t)src->y) / ((real_t)image->h));
1003 glVertex2f(pos->w, 0);
1004 glEnd();
1005 glPopMatrix();
1006 glEnable(GL_DEPTH_TEST);
1007 }
1008
1009 /*-------------------------------------------------------------------------------
1010
1011 drawSky3D
1012
1013 Draws the sky as an image whose position depends upon the given camera
1014 position
1015
1016 -------------------------------------------------------------------------------*/
1017
drawSky3D(view_t * camera,SDL_Surface * tex)1018 void drawSky3D( view_t* camera, SDL_Surface* tex )
1019 {
1020 real_t screenfactor;
1021 int skyx, skyy;
1022 SDL_Rect dest;
1023 SDL_Rect src;
1024
1025 // move the images differently depending upon the screen size
1026 screenfactor = xres / 320.0;
1027
1028 // bitmap offsets
1029 skyx = -camera->ang * ((320 * screenfactor) / (PI / 2.0));
1030 skyy = (-114 * screenfactor - camera->vang);
1031
1032 src.x = -skyx;
1033 src.y = -skyy;
1034 src.w = (-skyx) + xres; // clip to the screen width
1035 src.h = (-skyy) + yres; // clip to the screen height
1036 dest.x = 0;
1037 dest.y = 0;
1038 dest.w = xres;
1039 dest.h = yres;
1040
1041 drawImage(tex, &src, &dest);
1042
1043 // draw the part of the last part of the sky (only appears when angle > 270 deg.)
1044 if ( skyx < -960 * screenfactor )
1045 {
1046 dest.x = 1280 * screenfactor + skyx;
1047 dest.y = 0;
1048 dest.w = xres;
1049 dest.h = yres;
1050 src.x = 0;
1051 src.y = -skyy;
1052 src.w = xres - (-skyx - 1280 * screenfactor);
1053 src.h = src.y + yres;
1054 drawImage(tex, &src, &dest);
1055 }
1056 }
1057
1058 /*-------------------------------------------------------------------------------
1059
1060 drawLayer / drawBackground / drawForeground
1061
1062 Draws the world tiles that are viewable at the given camera coordinates
1063
1064 -------------------------------------------------------------------------------*/
1065
drawLayer(long camx,long camy,int z,map_t * map)1066 void drawLayer(long camx, long camy, int z, map_t* map)
1067 {
1068 long x, y;
1069 long minx, miny, maxx, maxy;
1070 int index;
1071 SDL_Rect pos;
1072
1073 minx = std::max<long int>(camx >> TEXTUREPOWER, 0);
1074 maxx = std::min<long int>((camx >> TEXTUREPOWER) + xres / TEXTURESIZE + 2, map->width); //TODO: Why are long int and unsigned int being compared?
1075 miny = std::max<long int>(camy >> TEXTUREPOWER, 0);
1076 maxy = std::min<long int>((camy >> TEXTUREPOWER) + yres / TEXTURESIZE + 2, map->height); //TODO: Why are long int and unsigned int being compared?
1077 for ( y = miny; y < maxy; y++ )
1078 {
1079 for ( x = minx; x < maxx; x++ )
1080 {
1081 index = map->tiles[z + y * MAPLAYERS + x * MAPLAYERS * map->height];
1082 if ( index > 0)
1083 {
1084 pos.x = (x << TEXTUREPOWER) - camx;
1085 pos.y = (y << TEXTUREPOWER) - camy;
1086 pos.w = TEXTURESIZE;
1087 pos.h = TEXTURESIZE;
1088 if ( index >= 0 && index < numtiles )
1089 {
1090 if ( tiles[index] != NULL )
1091 {
1092 drawImageScaled(tiles[index], NULL, &pos);
1093 }
1094 else
1095 {
1096 drawImageScaled(sprites[0], NULL, &pos);
1097 }
1098 }
1099 else
1100 {
1101 drawImageScaled(sprites[0], NULL, &pos);
1102 }
1103 }
1104 }
1105 }
1106 }
1107
drawBackground(long camx,long camy)1108 void drawBackground(long camx, long camy)
1109 {
1110 long z;
1111 for ( z = 0; z < OBSTACLELAYER; z++ )
1112 {
1113 drawLayer(camx, camy, z, &map);
1114 }
1115 }
1116
drawForeground(long camx,long camy)1117 void drawForeground(long camx, long camy)
1118 {
1119 long z;
1120 for ( z = OBSTACLELAYER; z < MAPLAYERS; z++ )
1121 {
1122 drawLayer(camx, camy, z, &map);
1123 }
1124 }
1125
1126 /*-------------------------------------------------------------------------------
1127
1128 drawClearBuffers
1129
1130 clears the screen and resets zbuffer and vismap
1131
1132 -------------------------------------------------------------------------------*/
1133
drawClearBuffers()1134 void drawClearBuffers()
1135 {
1136 // empty video and input buffers
1137 if ( zbuffer != NULL )
1138 {
1139 memset( zbuffer, 0, xres * yres * sizeof(real_t) );
1140 }
1141 if ( clickmap != NULL )
1142 {
1143 memset( clickmap, 0, xres * yres * sizeof(Entity*) );
1144 }
1145 if ( vismap != NULL )
1146 {
1147 int c, i = map.width * map.height;
1148 for ( c = 0; c < i; c++ )
1149 {
1150 vismap[c] = false;
1151 }
1152 }
1153
1154 // clear the screen
1155 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1156 drawRect(NULL, 0, 255);
1157 }
1158
1159 /*-------------------------------------------------------------------------------
1160
1161 raycast
1162
1163 Performs raycasting from the given camera's position through the
1164 environment to update minimap and vismap
1165
1166 -------------------------------------------------------------------------------*/
1167
raycast(view_t * camera,int mode,bool updateVismap)1168 void raycast(view_t* camera, int mode, bool updateVismap)
1169 {
1170 long posx, posy;
1171 real_t fracx, fracy;
1172 long inx, iny, inx2, iny2;
1173 real_t rx, ry;
1174 real_t d, dstart, dend;
1175 long sx;
1176 real_t arx, ary;
1177 long dincx, dincy;
1178 real_t dval0, dval1;
1179
1180 Uint8 light;
1181 Sint32 z;
1182 bool zhit[MAPLAYERS], wallhit;
1183
1184 posx = floor(camera->x);
1185 posy = floor(camera->y); // integer coordinates
1186 fracx = camera->x - posx;
1187 fracy = camera->y - posy; // fraction coordinates
1188
1189 real_t wfov = (fov * camera->winw / camera->winh) * PI / 180.f;
1190 dstart = CLIPNEAR / 16.0;
1191
1192 // ray vector
1193 rx = cos(camera->ang - wfov / 2.f);
1194 ry = sin(camera->ang - wfov / 2.f);
1195
1196 if ( updateVismap && posx >= 0 && posy >= 0 && posx < map.width && posy < map.height )
1197 {
1198 vismap[posy + posx * map.height] = true;
1199 }
1200 for ( sx = 0; sx < camera->winw; sx++ ) // for every column of the screen
1201 {
1202 inx = posx;
1203 iny = posy;
1204 inx2 = inx;
1205 iny2 = iny;
1206
1207 arx = 0;
1208 if (rx)
1209 {
1210 arx = 1.0 / fabs(rx); // distance increments
1211 }
1212 ary = 0;
1213 if (ry)
1214 {
1215 ary = 1.0 / fabs(ry);
1216 }
1217
1218 // dval0=dend+1 is there to prevent infinite loops when ray is parallel to axis
1219 dincx = 0;
1220 dval0 = 1e32;
1221 dincy = 0;
1222 dval1 = 1e32;
1223
1224 // calculate integer coordinate increments
1225 // x-axis:
1226 if (rx < 0)
1227 {
1228 dincx = -1;
1229 dval0 = fracx * arx;
1230 }
1231 else if (rx > 0)
1232 {
1233 dincx = 1;
1234 dval0 = (1 - fracx) * arx;
1235 }
1236
1237 // y-axis:
1238 if (ry < 0)
1239 {
1240 dincy = -1;
1241 dval1 = fracy * ary;
1242 }
1243 else if (ry > 0)
1244 {
1245 dincy = 1;
1246 dval1 = (1 - fracy) * ary;
1247 }
1248
1249 d = 0;
1250 dend = CLIPFAR / 16;
1251 do
1252 {
1253 inx2 = inx;
1254 iny2 = iny;
1255
1256 // move the ray one square forward
1257 if (dval1 > dval0)
1258 {
1259 inx += dincx;
1260 d = dval0;
1261 dval0 += arx;
1262 }
1263 else
1264 {
1265 iny += dincy;
1266 d = dval1;
1267 dval1 += ary;
1268 }
1269
1270 if ( inx >= 0 && iny >= 0 && inx < map.width && iny < map.height )
1271 {
1272 if ( updateVismap )
1273 {
1274 vismap[iny + inx * map.height] = true;
1275 }
1276 for ( z = 0; z < MAPLAYERS; z++ )
1277 {
1278 zhit[z] = false;
1279 if ( map.tiles[z + iny * MAPLAYERS + inx * MAPLAYERS * map.height] && d > dstart ) // hit something solid
1280 {
1281 zhit[z] = true;
1282
1283 // collect light information
1284 if ( inx2 >= 0 && iny2 >= 0 && inx2 < map.width && iny2 < map.height )
1285 {
1286 if ( map.tiles[z + iny2 * MAPLAYERS + inx2 * MAPLAYERS * map.height] )
1287 {
1288 continue;
1289 }
1290 light = std::min(std::max(0, lightmap[iny2 + inx2 * map.height]), 255);
1291 }
1292 else
1293 {
1294 light = 128;
1295 }
1296
1297 // update minimap
1298 if ( mode == REALCOLORS )
1299 if ( d < 16 && z == OBSTACLELAYER )
1300 if ( light > 0 )
1301 {
1302 minimap[iny][inx] = 2; // wall space
1303 }
1304 }
1305 else if ( z == OBSTACLELAYER && mode == REALCOLORS )
1306 {
1307 // update minimap to show empty region
1308 if ( inx >= 0 && iny >= 0 && inx < map.width && iny < map.height )
1309 {
1310 light = std::min(std::max(0, lightmap[iny + inx * map.height]), 255);
1311 }
1312 else
1313 {
1314 light = 128;
1315 }
1316 if ( d < 16 )
1317 {
1318 if ( light > 0 && map.tiles[iny * MAPLAYERS + inx * MAPLAYERS * map.height] )
1319 {
1320 minimap[iny][inx] = 1; // walkable space
1321 }
1322 else if ( map.tiles[z + iny * MAPLAYERS + inx * MAPLAYERS * map.height] )
1323 {
1324 minimap[iny][inx] = 0; // no floor
1325 }
1326 }
1327 }
1328 }
1329 wallhit = true;
1330 for ( z = 0; z < MAPLAYERS; z++ )
1331 if ( zhit[z] == false )
1332 {
1333 wallhit = false;
1334 }
1335 if ( wallhit == true )
1336 {
1337 break;
1338 }
1339 }
1340 }
1341 while (d < dend);
1342
1343 // new ray vector for next column
1344 rx = cos(camera->ang - wfov / 2.f + (wfov / camera->winw) * sx);
1345 ry = sin(camera->ang - wfov / 2.f + (wfov / camera->winw) * sx);
1346 }
1347 }
1348
1349 /*-------------------------------------------------------------------------------
1350
1351 drawEntities3D
1352
1353 Draws all entities in the level as either voxel models or sprites
1354
1355 -------------------------------------------------------------------------------*/
1356
drawEntities3D(view_t * camera,int mode)1357 void drawEntities3D(view_t* camera, int mode)
1358 {
1359 node_t* node;
1360 Entity* entity;
1361 long x, y;
1362
1363 if ( map.entities->first == nullptr )
1364 {
1365 return;
1366 }
1367
1368 glEnable(GL_SCISSOR_TEST);
1369 glScissor(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
1370
1371 for ( node = map.entities->first; node != nullptr; node = node->next )
1372 {
1373 entity = (Entity*)node->element;
1374 if ( entity->flags[INVISIBLE] )
1375 {
1376 continue;
1377 }
1378 if ( entity->flags[UNCLICKABLE] && mode == ENTITYUIDS )
1379 {
1380 continue;
1381 }
1382 if ( entity->flags[GENIUS] )
1383 {
1384 // genius entities are not drawn when the camera is inside their bounding box
1385 if ( camera->x >= (entity->x - entity->sizex) / 16 && camera->x <= (entity->x + entity->sizex) / 16 )
1386 if ( camera->y >= (entity->y - entity->sizey) / 16 && camera->y <= (entity->y + entity->sizey) / 16 )
1387 {
1388 continue;
1389 }
1390 }
1391 x = entity->x / 16;
1392 y = entity->y / 16;
1393 if ( x >= 0 && y >= 0 && x < map.width && y < map.height )
1394 {
1395 if ( vismap[y + x * map.height] || entity->flags[OVERDRAW] || entity->monsterEntityRenderAsTelepath == 1 )
1396 {
1397 if ( entity->flags[SPRITE] == false )
1398 {
1399 glDrawVoxel(camera, entity, mode);
1400 }
1401 else
1402 {
1403 if ( entity->behavior == &actSpriteNametag )
1404 {
1405 int playersTag = playerEntityMatchesUid(entity->parent);
1406 if ( playersTag >= 0 )
1407 {
1408 glDrawSpriteFromImage(camera, entity, stats[playersTag]->name, mode);
1409 }
1410 }
1411 else
1412 {
1413 glDrawSprite(camera, entity, mode);
1414 }
1415 }
1416 }
1417 }
1418 else
1419 {
1420 if ( entity->flags[SPRITE] == false )
1421 {
1422 glDrawVoxel(camera, entity, mode);
1423 }
1424 else
1425 {
1426 glDrawSprite(camera, entity, mode);
1427 }
1428 }
1429 }
1430
1431 glDisable(GL_SCISSOR_TEST);
1432 glScissor(0, 0, xres, yres);
1433 }
1434
1435 /*-------------------------------------------------------------------------------
1436
1437 drawEntities2D
1438
1439 Draws all entities in the level as sprites while accounting for the given
1440 camera coordinates
1441
1442 -------------------------------------------------------------------------------*/
1443
drawEntities2D(long camx,long camy)1444 void drawEntities2D(long camx, long camy)
1445 {
1446 node_t* node;
1447 Entity* entity;
1448 SDL_Rect pos, box;
1449 int offsetx = 0;
1450 int offsety = 0;
1451
1452 if ( map.entities->first == nullptr )
1453 {
1454 return;
1455 }
1456
1457 // draw entities
1458 for ( node = map.entities->first; node != nullptr; node = node->next )
1459 {
1460 entity = (Entity*)node->element;
1461 if ( entity->flags[INVISIBLE] )
1462 {
1463 continue;
1464 }
1465 pos.x = entity->x * (TEXTURESIZE / 16) - camx;
1466 pos.y = entity->y * (TEXTURESIZE / 16) - camy;
1467 pos.w = TEXTURESIZE;
1468 pos.h = TEXTURESIZE;
1469 //ttfPrintText(ttf8, 100, 100, inputstr); debug any errant text input in editor
1470
1471 if ( entity->sprite >= 0 && entity->sprite < numsprites )
1472 {
1473 if ( sprites[entity->sprite] != nullptr )
1474 {
1475 if ( entity == selectedEntity )
1476 {
1477 // draws a box around the sprite
1478 box.w = TEXTURESIZE;
1479 box.h = TEXTURESIZE;
1480 box.x = pos.x;
1481 box.y = pos.y;
1482 drawRect(&box, SDL_MapRGB(mainsurface->format, 255, 0, 0), 255);
1483 box.w = TEXTURESIZE - 2;
1484 box.h = TEXTURESIZE - 2;
1485 box.x = pos.x + 1;
1486 box.y = pos.y + 1;
1487 drawRect(&box, SDL_MapRGB(mainsurface->format, 0, 0, 255), 255);
1488 }
1489
1490 // if item sprite and the item index is not 0 (NULL), or 1 (RANDOM)
1491 if ( entity->sprite == 8 && entity->skill[10] > 1 )
1492 {
1493 // draw the item sprite in the editor layout
1494 Item* tmpItem = newItem(static_cast<ItemType>(entity->skill[10] - 2), static_cast<Status>(0), 0, 0, 0, 0, nullptr);
1495 drawImageScaled(itemSprite(tmpItem), nullptr, &pos);
1496 free(tmpItem);
1497 }
1498 else if ( entity->sprite == 133 )
1499 {
1500 pos.y += sprites[entity->sprite]->h / 2;
1501 pos.x += sprites[entity->sprite]->w / 2;
1502 switch ( entity->signalInputDirection )
1503 {
1504 case 0:
1505 drawImageRotatedAlpha(sprites[entity->sprite], nullptr, &pos, 0.f, 255);
1506 break;
1507 case 1:
1508 drawImageRotatedAlpha(sprites[entity->sprite], nullptr, &pos, 3 * PI / 2, 255);
1509 break;
1510 case 2:
1511 drawImageRotatedAlpha(sprites[entity->sprite], nullptr, &pos, PI, 255);
1512 break;
1513 case 3:
1514 drawImageRotatedAlpha(sprites[entity->sprite], nullptr, &pos, PI / 2, 255);
1515 break;
1516 }
1517 }
1518 else
1519 {
1520 // draw sprite normally from sprites list
1521 drawImageScaled(sprites[entity->sprite], nullptr, &pos);
1522 }
1523 }
1524 else
1525 {
1526 if ( entity == selectedEntity )
1527 {
1528 // draws a box around the sprite
1529 box.w = TEXTURESIZE;
1530 box.h = TEXTURESIZE;
1531 box.x = pos.x;
1532 box.y = pos.y;
1533 drawRect(&box, SDL_MapRGB(mainsurface->format, 255, 0, 0), 255);
1534 box.w = TEXTURESIZE - 2;
1535 box.h = TEXTURESIZE - 2;
1536 box.x = pos.x + 1;
1537 box.y = pos.y + 1;
1538 drawRect(&box, SDL_MapRGB(mainsurface->format, 0, 0, 255), 255);
1539 }
1540 drawImageScaled(sprites[0], nullptr, &pos);
1541 }
1542 }
1543 else
1544 {
1545 if ( entity == selectedEntity )
1546 {
1547 // draws a box around the sprite
1548 box.w = TEXTURESIZE;
1549 box.h = TEXTURESIZE;
1550 box.x = pos.x;
1551 box.y = pos.y;
1552 drawRect(&box, SDL_MapRGB(mainsurface->format, 255, 0, 0), 255);
1553 box.w = TEXTURESIZE - 2;
1554 box.h = TEXTURESIZE - 2;
1555 box.x = pos.x + 1;
1556 box.y = pos.y + 1;
1557 drawRect(&box, SDL_MapRGB(mainsurface->format, 0, 0, 255), 255);
1558 }
1559 drawImageScaled(sprites[0], nullptr, &pos);
1560 }
1561 }
1562
1563 // draw hover text for entities over the top of sprites.
1564 for ( node = map.entities->first; node != nullptr && (openwindow == 0 && savewindow == 0); node = node->next )
1565 {
1566 entity = (Entity*)node->element;
1567 if ( entity->flags[INVISIBLE] )
1568 {
1569 continue;
1570 }
1571 pos.x = entity->x * (TEXTURESIZE / 16) - camx;
1572 pos.y = entity->y * (TEXTURESIZE / 16) - camy;
1573 pos.w = TEXTURESIZE;
1574 pos.h = TEXTURESIZE;
1575 //ttfPrintText(ttf8, 100, 100, inputstr); debug any errant text input in editor
1576
1577 if ( entity->sprite >= 0 && entity->sprite < numsprites )
1578 {
1579 if ( sprites[entity->sprite] != nullptr )
1580 {
1581 if ( entity == selectedEntity )
1582 {
1583 int spriteType = checkSpriteType(selectedEntity->sprite);
1584 char tmpStr[1024] = "";
1585 char tmpStr2[1024] = "";
1586 int padx = pos.x + 10;
1587 int pady = pos.y - 40;
1588 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1589 Uint32 colorWhite = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1590 switch ( spriteType )
1591 {
1592 case 1: //monsters
1593 pady += 10;
1594 if ( entity->getStats() != nullptr ) {
1595 strcpy(tmpStr, spriteEditorNameStrings[selectedEntity->sprite]);
1596 ttfPrintText(ttf8, padx, pady - 10, tmpStr);
1597 snprintf(tmpStr, sizeof(entity->getStats()->name), "Name: %s", entity->getStats()->name);
1598 ttfPrintText(ttf8, padx, pady, tmpStr);
1599 snprintf(tmpStr, 10, "HP: %d", entity->getStats()->MAXHP);
1600 ttfPrintText(ttf8, padx, pady + 10, tmpStr);
1601 snprintf(tmpStr, 10, "Level: %d", entity->getStats()->LVL);
1602 ttfPrintText(ttf8, padx, pady + 20, tmpStr);
1603 }
1604
1605
1606 break;
1607 case 2: //chest
1608 pady += 5;
1609 strcpy(tmpStr, spriteEditorNameStrings[selectedEntity->sprite]);
1610 ttfPrintText(ttf8, padx, pady, tmpStr);
1611 switch ( (int)entity->yaw )
1612 {
1613 case 0:
1614 strcpy(tmpStr, "Facing: EAST");
1615 break;
1616 case 1:
1617 strcpy(tmpStr, "Facing: SOUTH");
1618 break;
1619 case 2:
1620 strcpy(tmpStr, "Facing: WEST");
1621 break;
1622 case 3:
1623 strcpy(tmpStr, "Facing: NORTH");
1624 break;
1625 default:
1626 strcpy(tmpStr, "Facing: Invalid");
1627 break;
1628
1629 }
1630 ttfPrintText(ttf8, padx, pady + 10, tmpStr);
1631
1632 switch ( entity->skill[9] )
1633 {
1634 case 0:
1635 strcpy(tmpStr, "Type: Random");
1636 break;
1637 case 1:
1638 strcpy(tmpStr, "Type: Garbage");
1639 break;
1640 case 2:
1641 strcpy(tmpStr, "Type: Food");
1642 break;
1643 case 3:
1644 strcpy(tmpStr, "Type: Jewelry");
1645 break;
1646 case 4:
1647 strcpy(tmpStr, "Type: Equipment");
1648 break;
1649 case 5:
1650 strcpy(tmpStr, "Type: Tools");
1651 break;
1652 case 6:
1653 strcpy(tmpStr, "Type: Magical");
1654 break;
1655 case 7:
1656 strcpy(tmpStr, "Type: Potions");
1657 break;
1658 case 8:
1659 strcpy(tmpStr, "Type: Empty");
1660 break;
1661 default:
1662 strcpy(tmpStr, "Type: Random");
1663 break;
1664 }
1665 ttfPrintText(ttf8, padx, pady + 20, tmpStr);
1666 break;
1667
1668 case 3: //Items
1669 pady += 5;
1670 strcpy(tmpStr, itemNameStrings[selectedEntity->skill[10]]);
1671 ttfPrintText(ttf8, padx, pady - 20, tmpStr);
1672 color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1673 pady += 2;
1674
1675 strcpy(tmpStr, "Status: ");
1676 ttfPrintTextColor(ttf8, padx, pady - 10, colorWhite, 1, tmpStr);
1677 switch ( (int)selectedEntity->skill[11] )
1678 {
1679 case 1:
1680 strcpy(tmpStr, "Broken");
1681 color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
1682 break;
1683 case 2:
1684 strcpy(tmpStr, "Decrepit");
1685 color = SDL_MapRGB(mainsurface->format, 200, 128, 0);
1686 break;
1687 case 3:
1688 strcpy(tmpStr, "Worn");
1689 color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
1690 break;
1691 case 4:
1692 strcpy(tmpStr, "Servicable");
1693 color = SDL_MapRGB(mainsurface->format, 128, 200, 0);
1694 break;
1695 case 5:
1696 strcpy(tmpStr, "Excellent");
1697 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
1698 break;
1699 default:
1700 strcpy(tmpStr, "?");
1701 color = SDL_MapRGB(mainsurface->format, 0, 168, 255);
1702 break;
1703 }
1704 ttfPrintTextColor(ttf8, padx + 56, pady - 10, color, 1, tmpStr);
1705
1706 strcpy(tmpStr, "Bless: ");
1707 ttfPrintTextColor(ttf8, padx, pady, colorWhite, 1, tmpStr);
1708 if ( selectedEntity->skill[12] < 0 )
1709 {
1710 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[12]);
1711 color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
1712 }
1713 else if ( selectedEntity->skill[12] == 0 )
1714 {
1715 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[12]);
1716 color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
1717 }
1718 else if ( selectedEntity->skill[12] == 10 )
1719 {
1720 strcpy(tmpStr2, "?");
1721 color = SDL_MapRGB(mainsurface->format, 0, 168, 255);
1722 }
1723 else
1724 {
1725 snprintf(tmpStr2, 10, "+%d", selectedEntity->skill[12]);
1726 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
1727 }
1728 ttfPrintTextColor(ttf8, padx + 48, pady, color, 1, tmpStr2);
1729
1730 strcpy(tmpStr, "Qty: ");
1731 ttfPrintTextColor(ttf8, padx, pady + 10, colorWhite, 1, tmpStr);
1732 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[13]);
1733 ttfPrintTextColor(ttf8, padx + 32, pady + 10, colorWhite, 1, tmpStr2);
1734
1735 pady += 2;
1736 strcpy(tmpStr, "Identified: ");
1737 ttfPrintTextColor(ttf8, padx, pady + 20, colorWhite, 1, tmpStr);
1738 if ( (int)selectedEntity->skill[15] == 0 )
1739 {
1740 strcpy(tmpStr2, "No");
1741 color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
1742 }
1743 else if ( (int)selectedEntity->skill[15] == 1 )
1744 {
1745 strcpy(tmpStr2, "Yes");
1746 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
1747 }
1748 else
1749 {
1750 strcpy(tmpStr2, "?");
1751 color = SDL_MapRGB(mainsurface->format, 0, 168, 255);
1752 }
1753 ttfPrintTextColor(ttf8, padx + 80, pady + 20, color, 1, tmpStr2);
1754 break;
1755 case 4: //summoning trap
1756 pady += 5;
1757 offsety = -40;
1758 strcpy(tmpStr, spriteEditorNameStrings[selectedEntity->sprite]);
1759 ttfPrintText(ttf8, padx, pady + offsety, tmpStr);
1760
1761 offsety += 10;
1762 strcpy(tmpStr, "Type: ");
1763 offsetx = strlen(tmpStr) * 8 - 8;
1764 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1765 strcpy(tmpStr2, monsterEditorNameStrings[entity->skill[0]]);
1766 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1767
1768 offsety += 10;
1769 strcpy(tmpStr, "Qty: ");
1770 offsetx = strlen(tmpStr) * 8 - 8;
1771 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1772 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[1]);
1773 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1774
1775 offsety += 10;
1776 strcpy(tmpStr, "Time: ");
1777 offsetx = strlen(tmpStr) * 8 - 8;
1778 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1779 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[2]);
1780 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1781
1782 offsety += 10;
1783 strcpy(tmpStr, "Amount: ");
1784 offsetx = strlen(tmpStr) * 8 - 8;
1785 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1786 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[3]);
1787 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1788
1789 offsety += 10;
1790 strcpy(tmpStr, "Power to: ");
1791 offsetx = strlen(tmpStr) * 8 - 8;
1792 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1793 if ( selectedEntity->skill[4] == 1 )
1794 {
1795 strcpy(tmpStr2, "Spawn");
1796 }
1797 else
1798 {
1799 strcpy(tmpStr2, "Disable");
1800 }
1801 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1802
1803 offsety += 10;
1804 strcpy(tmpStr, "Stop Chance: ");
1805 offsetx = strlen(tmpStr) * 8 - 8;
1806 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1807 snprintf(tmpStr2, 10, "%d", selectedEntity->skill[5]);
1808 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1809 break;
1810 case 5: //power crystal
1811 pady += 5;
1812 offsety = -20;
1813 strcpy(tmpStr, spriteEditorNameStrings[selectedEntity->sprite]);
1814 ttfPrintText(ttf8, padx, pady + offsety, tmpStr);
1815
1816 offsety += 10;
1817 strcpy(tmpStr, "Facing: ");
1818 ttfPrintText(ttf8, padx, pady + offsety, tmpStr);
1819 offsetx = strlen(tmpStr) * 8 - 8;
1820 switch ( (int)entity->yaw )
1821 {
1822 case 0:
1823 strcpy(tmpStr2, "EAST");
1824 break;
1825 case 1:
1826 strcpy(tmpStr2, "SOUTH");
1827 break;
1828 case 2:
1829 strcpy(tmpStr2, "WEST");
1830 break;
1831 case 3:
1832 strcpy(tmpStr2, "NORTH");
1833 break;
1834 default:
1835 strcpy(tmpStr2, "Invalid");
1836 break;
1837
1838 }
1839 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1840
1841 offsety += 10;
1842 strcpy(tmpStr, "Nodes: ");
1843 offsetx = strlen(tmpStr) * 8 - 8;
1844 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1845 snprintf(tmpStr2, 10, "%d", selectedEntity->crystalNumElectricityNodes);
1846 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1847
1848 offsety += 10;
1849 strcpy(tmpStr, "Rotation: ");
1850 offsetx = strlen(tmpStr) * 8 - 8;
1851 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1852 switch ( (int)entity->crystalTurnReverse )
1853 {
1854 case 0:
1855 strcpy(tmpStr2, "Clockwise");
1856 break;
1857 case 1:
1858 strcpy(tmpStr2, "Anti-Clockwise");
1859 break;
1860 default:
1861 strcpy(tmpStr2, "Invalid");
1862 break;
1863
1864 }
1865 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1866
1867 offsety += 10;
1868 strcpy(tmpStr, "Spell to Activate: ");
1869 offsetx = strlen(tmpStr) * 8 - 8;
1870 ttfPrintTextColor(ttf8, padx, pady + offsety, colorWhite, 1, tmpStr);
1871 switch ( (int)entity->crystalSpellToActivate )
1872 {
1873 case 0:
1874 strcpy(tmpStr2, "No");
1875 break;
1876 case 1:
1877 strcpy(tmpStr2, "Yes");
1878 break;
1879 default:
1880 strcpy(tmpStr2, "Invalid");
1881 break;
1882
1883 }
1884 ttfPrintText(ttf8, padx + offsetx, pady + offsety, tmpStr2);
1885 break;
1886 case 16:
1887 case 13:
1888 {
1889 char buf[256] = "";
1890 int totalChars = 0;
1891 for ( int i = (spriteType == 16 ? 4 : 8); i < 60; ++i )
1892 {
1893 if ( selectedEntity->skill[i] != 0 && i != 28 ) // skill[28] is circuit status.
1894 {
1895 for ( int c = 0; c < 4; ++c )
1896 {
1897 if ( static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF) == '\0'
1898 && i != 59 && selectedEntity->skill[i + 1] != 0 )
1899 {
1900 // don't add '\0' termination unless the next skill slot is empty as we have more data to read.
1901 }
1902 else
1903 {
1904 buf[totalChars] = static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF);
1905 ++totalChars;
1906 }
1907 }
1908 }
1909 }
1910 if ( buf[totalChars] != '\0' )
1911 {
1912 buf[totalChars] = '\0';
1913 }
1914 int numLines = 0;
1915 std::vector<std::string> lines;
1916 lines.push_back(spriteEditorNameStrings[selectedEntity->sprite]);
1917
1918 strncpy(tmpStr, buf, 48);
1919 if ( strcmp(tmpStr, "") )
1920 {
1921 lines.push_back(tmpStr);
1922 }
1923 strncpy(tmpStr, buf + 48, 48);
1924 if ( strcmp(tmpStr, "") )
1925 {
1926 lines.push_back(tmpStr);
1927 }
1928 strncpy(tmpStr, buf + 96, 48);
1929 if ( strcmp(tmpStr, "") )
1930 {
1931 lines.push_back(tmpStr);
1932 }
1933 strncpy(tmpStr, buf + 144, 48);
1934 if ( strcmp(tmpStr, "") )
1935 {
1936 lines.push_back(tmpStr);
1937 }
1938 strncpy(tmpStr, buf + 192, 48);
1939 if ( strcmp(tmpStr, "") )
1940 {
1941 lines.push_back(tmpStr);
1942 }
1943 if ( lines.size() > 3 )
1944 {
1945 offsety -= (lines.size() - 2) * 5;
1946 }
1947
1948 size_t longestLine = 0;
1949 for ( auto it : lines )
1950 {
1951 longestLine = std::max(longestLine, strlen(it.c_str()));
1952 }
1953
1954 SDL_Rect tooltip;
1955 tooltip.x = padx + offsetx - 4;
1956 tooltip.w = TTF8_WIDTH * longestLine + 8;
1957 tooltip.y = pady + offsety - 4;
1958 tooltip.h = lines.size() * TTF8_HEIGHT + 8;
1959 if ( lines.size() > 1 )
1960 {
1961 drawTooltip(&tooltip);
1962 }
1963 for ( auto it : lines )
1964 {
1965 ttfPrintText(ttf8, padx + offsetx, pady + offsety, it.c_str());
1966 offsety += 10;
1967 }
1968 }
1969 break;
1970 default:
1971 strcpy(tmpStr, spriteEditorNameStrings[selectedEntity->sprite]);
1972 ttfPrintText(ttf8, padx, pady + 20, tmpStr);
1973 break;
1974
1975 }
1976 }
1977 else if ( (omousex / TEXTURESIZE) * 32 == pos.x && (omousey / TEXTURESIZE) * 32 == pos.y &&
1978 selectedEntity == NULL && hovertext )
1979 {
1980 // handle mouseover sprite name tooltip in main editor screen
1981 int padx = pos.x + 10;
1982 int pady = pos.y - 20;
1983 int spriteType = checkSpriteType(entity->sprite);
1984 //offsety = 0;
1985 Stat* tmpStats = nullptr;
1986 if ( spriteType == 1 )
1987 {
1988 tmpStats = entity->getStats();
1989 if ( tmpStats != nullptr )
1990 {
1991 if ( strcmp(tmpStats->name, "") != 0 )
1992 {
1993 ttfPrintText(ttf8, padx, pady - offsety, tmpStats->name);
1994 offsety += 10;
1995 }
1996 ttfPrintText(ttf8, padx, pady - offsety, spriteEditorNameStrings[entity->sprite]);
1997 offsety += 10;
1998 }
1999 }
2000 else if ( spriteType == 3 )
2001 {
2002 ttfPrintText(ttf8, padx, pady - offsety, itemNameStrings[entity->skill[10]]);
2003 offsety += 10;
2004 }
2005 else
2006 {
2007 ttfPrintText(ttf8, padx, pady - offsety, spriteEditorNameStrings[entity->sprite]);
2008 offsety += 10;
2009 }
2010 }
2011 }
2012 }
2013 }
2014 }
2015
2016 /*-------------------------------------------------------------------------------
2017
2018 drawGrid
2019
2020 Draws a white line grid for the tile map
2021
2022 -------------------------------------------------------------------------------*/
2023
drawGrid(long camx,long camy)2024 void drawGrid(long camx, long camy)
2025 {
2026 long x, y;
2027 Uint32 color;
2028
2029 color = SDL_MapRGB(mainsurface->format, 127, 127, 127);
2030 drawLine(-camx, (map.height << TEXTUREPOWER) - camy, (map.width << TEXTUREPOWER) - camx, (map.height << TEXTUREPOWER) - camy, color, 255);
2031 drawLine((map.width << TEXTUREPOWER) - camx, -camy, (map.width << TEXTUREPOWER) - camx, (map.height << TEXTUREPOWER) - camy, color, 255);
2032 for ( y = 0; y < map.height; y++ )
2033 {
2034 for ( x = 0; x < map.width; x++ )
2035 {
2036 drawLine((x << TEXTUREPOWER) - camx, (y << TEXTUREPOWER) - camy, ((x + 1) << TEXTUREPOWER) - camx, (y << TEXTUREPOWER) - camy, color, 255);
2037 drawLine((x << TEXTUREPOWER) - camx, (y << TEXTUREPOWER) - camy, (x << TEXTUREPOWER) - camx, ((y + 1) << TEXTUREPOWER) - camy, color, 255);
2038 }
2039 }
2040 }
2041
2042 /*-------------------------------------------------------------------------------
2043
2044 drawEditormap
2045
2046 Draws a minimap in the upper right corner of the screen to represent
2047 the screen's position relative to the rest of the level
2048
2049 -------------------------------------------------------------------------------*/
2050
drawEditormap(long camx,long camy)2051 void drawEditormap(long camx, long camy)
2052 {
2053 SDL_Rect src, osrc;
2054
2055 src.x = xres - 120;
2056 src.y = 24;
2057 src.w = 112;
2058 src.h = 112;
2059 drawRect(&src, SDL_MapRGB(mainsurface->format, 0, 0, 0), 255);
2060
2061 // initial box dimensions
2062 src.x = (xres - 120) + (((real_t)camx / TEXTURESIZE) * 112.0) / map.width;
2063 src.y = 24 + (((real_t)camy / TEXTURESIZE) * 112.0) / map.height;
2064 src.w = (112.0 / map.width) * ((real_t)xres / TEXTURESIZE);
2065 src.h = (112.0 / map.height) * ((real_t)yres / TEXTURESIZE);
2066
2067 // clip at left edge
2068 if ( src.x < xres - 120 )
2069 {
2070 src.w -= (xres - 120) - src.x;
2071 src.x = xres - 120;
2072 }
2073
2074 // clip at right edge
2075 if ( src.x + src.w > xres - 8 )
2076 {
2077 src.w = xres - 8 - src.x;
2078 }
2079
2080 // clip at top edge
2081 if ( src.y < 24 )
2082 {
2083 src.h -= 24 - src.y;
2084 src.y = 24;
2085 }
2086
2087 // clip at bottom edge
2088 if ( src.y + src.h > 136 )
2089 {
2090 src.h = 136 - src.y;
2091 }
2092
2093 osrc.x = src.x + 1;
2094 osrc.y = src.y + 1;
2095 osrc.w = src.w - 2;
2096 osrc.h = src.h - 2;
2097 drawRect(&src, SDL_MapRGB(mainsurface->format, 255, 255, 255), 255);
2098 drawRect(&osrc, SDL_MapRGB(mainsurface->format, 0, 0, 0), 255);
2099 }
2100
2101 /*-------------------------------------------------------------------------------
2102
2103 drawWindow / drawDepressed
2104
2105 Draws a rectangular box that fills the area inside the given screen
2106 coordinates
2107
2108 -------------------------------------------------------------------------------*/
2109
drawWindow(int x1,int y1,int x2,int y2)2110 void drawWindow(int x1, int y1, int x2, int y2)
2111 {
2112 SDL_Rect src;
2113
2114 src.x = x1;
2115 src.y = y1;
2116 src.w = x2 - x1;
2117 src.h = y2 - y1;
2118 drawRect(&src, SDL_MapRGB(mainsurface->format, 160, 160, 192), 255);
2119 src.x = x1 + 1;
2120 src.y = y1 + 1;
2121 src.w = x2 - x1 - 1;
2122 src.h = y2 - y1 - 1;
2123 drawRect(&src, SDL_MapRGB(mainsurface->format, 96, 96, 128), 255);
2124 src.x = x1 + 1;
2125 src.y = y1 + 1;
2126 src.w = x2 - x1 - 2;
2127 src.h = y2 - y1 - 2;
2128 drawRect(&src, SDL_MapRGB(mainsurface->format, 128, 128, 160), 255);
2129 }
2130
drawDepressed(int x1,int y1,int x2,int y2)2131 void drawDepressed(int x1, int y1, int x2, int y2)
2132 {
2133 SDL_Rect src;
2134
2135 src.x = x1;
2136 src.y = y1;
2137 src.w = x2 - x1;
2138 src.h = y2 - y1;
2139 drawRect(&src, SDL_MapRGB(mainsurface->format, 96, 96, 128), 255);
2140 src.x = x1 + 1;
2141 src.y = y1 + 1;
2142 src.w = x2 - x1 - 1;
2143 src.h = y2 - y1 - 1;
2144 drawRect(&src, SDL_MapRGB(mainsurface->format, 160, 160, 192), 255);
2145 src.x = x1 + 1;
2146 src.y = y1 + 1;
2147 src.w = x2 - x1 - 2;
2148 src.h = y2 - y1 - 2;
2149 drawRect(&src, SDL_MapRGB(mainsurface->format, 128, 128, 160), 255);
2150 }
2151
drawWindowFancy(int x1,int y1,int x2,int y2)2152 void drawWindowFancy(int x1, int y1, int x2, int y2)
2153 {
2154 if (softwaremode)
2155 {
2156 // no fancy stuff in software mode
2157 drawWindow(x1, y1, x2, y2);
2158 return;
2159 }
2160
2161 // update projection
2162 glDisable(GL_DEPTH_TEST);
2163 glDisable(GL_LIGHTING);
2164 glMatrixMode(GL_PROJECTION);
2165 glViewport(0, 0, xres, yres);
2166 glLoadIdentity();
2167 glOrtho(0, xres, 0, yres, -1, 1);
2168 glMatrixMode(GL_MODELVIEW);
2169 glEnable(GL_BLEND);
2170
2171 // draw quads
2172 glColor3f(.25, .25, .25);
2173 glBindTexture(GL_TEXTURE_2D, 0);
2174 glBegin(GL_QUADS);
2175 glVertex2f(x1, yres - y1);
2176 glVertex2f(x1, yres - y2);
2177 glVertex2f(x2, yres - y2);
2178 glVertex2f(x2, yres - y1);
2179 glEnd();
2180 glColor3f(.5, .5, .5);
2181 glBindTexture(GL_TEXTURE_2D, 0);
2182 glBegin(GL_QUADS);
2183 glVertex2f(x1 + 1, yres - y1 - 1);
2184 glVertex2f(x1 + 1, yres - y2 + 1);
2185 glVertex2f(x2 - 1, yres - y2 + 1);
2186 glVertex2f(x2 - 1, yres - y1 - 1);
2187 glEnd();
2188 glColor3f(.75, .75, .75);
2189 glBindTexture(GL_TEXTURE_2D, texid[fancyWindow_bmp->refcount]); // wood texture
2190 glBegin(GL_QUADS);
2191 glTexCoord2f(0, 0);
2192 glVertex2f(x1 + 2, yres - y1 - 2);
2193 glTexCoord2f(0, (y2 - y1 - 4) / (real_t)tiles[30]->h);
2194 glVertex2f(x1 + 2, yres - y2 + 2);
2195 glTexCoord2f((x2 - x1 - 4) / (real_t)tiles[30]->w, (y2 - y1 - 4) / (real_t)tiles[30]->h);
2196 glVertex2f(x2 - 2, yres - y2 + 2);
2197 glTexCoord2f((x2 - x1 - 4) / (real_t)tiles[30]->w, 0);
2198 glVertex2f(x2 - 2, yres - y1 - 2);
2199 glEnd();
2200 }
2201
2202 /*-------------------------------------------------------------------------------
2203
2204 ttfPrintText / ttfPrintTextColor
2205
2206 Prints an unformatted utf8 string to the screen, returning the width of
2207 the message surface in pixels. ttfPrintTextColor() also takes a 32-bit
2208 color argument
2209
2210 -------------------------------------------------------------------------------*/
2211
2212 SDL_Rect errorRect = { 0 };
2213
ttfPrintTextColor(TTF_Font * font,int x,int y,Uint32 color,bool outline,const char * str)2214 SDL_Rect ttfPrintTextColor( TTF_Font* font, int x, int y, Uint32 color, bool outline, const char* str )
2215 {
2216 SDL_Rect pos = { x, y, 0, 0 };
2217 SDL_Surface* surf;
2218 int c;
2219
2220 if ( !str )
2221 {
2222 return errorRect;
2223 }
2224 char newStr[1024] = { 0 };
2225 strcpy(newStr, str);
2226
2227 // tokenize string
2228 for ( c = 0; c < strlen(newStr) + 1; c++ )
2229 {
2230 if ( newStr[c] == '\n' || newStr[c] == '\r' )
2231 {
2232 int offY = 0;
2233 if ( newStr[c] == '\n' )
2234 {
2235 offY = TTF_FontHeight(font);
2236 }
2237 newStr[c] = 0;
2238 ttfPrintTextColor(font, x, y + offY, color, outline, (char*)&newStr[c + 1]);
2239 break;
2240 }
2241 else if ( newStr[c] == 0 )
2242 {
2243 break;
2244 }
2245 }
2246
2247 if ( imgref > ttfTextCacheLimit )
2248 {
2249 // time to flush the cache.
2250 imgref -= 6144;
2251 for ( int i = 0; i < HASH_SIZE; ++i )
2252 {
2253 list_FreeAll(&ttfTextHash[i]);
2254 }
2255 printlog("notice: stored hash limit exceeded, clearing ttfTextHash...");
2256 }
2257
2258 // retrieve text surface
2259 if ( (surf = ttfTextHashRetrieve(ttfTextHash, newStr, font, outline)) == NULL )
2260 {
2261 // create the text outline surface
2262 if ( outline )
2263 {
2264 if ( font == ttf8 )
2265 {
2266 TTF_SetFontOutline(font, 1);
2267 }
2268 else
2269 {
2270 TTF_SetFontOutline(font, 2);
2271 }
2272 SDL_Color sdlColorBlack = { 0, 0, 0, 255 };
2273 surf = TTF_RenderUTF8_Blended(font, newStr, sdlColorBlack);
2274 }
2275 else
2276 {
2277 int w, h;
2278 TTF_SizeUTF8(font, newStr, &w, &h);
2279 if ( font == ttf8 )
2280 {
2281 surf = SDL_CreateRGBSurface(0, w + 2, h + 2,
2282 mainsurface->format->BitsPerPixel,
2283 mainsurface->format->Rmask,
2284 mainsurface->format->Gmask,
2285 mainsurface->format->Bmask,
2286 mainsurface->format->Amask
2287 );
2288 }
2289 else
2290 {
2291 surf = SDL_CreateRGBSurface(0, w + 4, h + 4,
2292 mainsurface->format->BitsPerPixel,
2293 mainsurface->format->Rmask,
2294 mainsurface->format->Gmask,
2295 mainsurface->format->Bmask,
2296 mainsurface->format->Amask
2297 );
2298 }
2299 }
2300
2301 if (!surf)
2302 {
2303 printlog("warning: failed to create the surface\n");
2304 return errorRect;
2305 }
2306 // create the text surface
2307 TTF_SetFontOutline(font, 0);
2308 SDL_Color sdlColorWhite = { 255, 255, 255, 255 };
2309 SDL_Surface* textSurf = TTF_RenderUTF8_Blended(font, newStr, sdlColorWhite);
2310
2311 // combine the surfaces
2312 if ( font == ttf8 )
2313 {
2314 pos.x = 1;
2315 pos.y = 1;
2316 }
2317 else
2318 {
2319 pos.x = 2;
2320 pos.y = 2;
2321 }
2322 SDL_BlitSurface(textSurf, NULL, surf, &pos);
2323 // load the text outline surface as a GL texture
2324 allsurfaces[imgref] = surf;
2325 allsurfaces[imgref]->refcount = imgref;
2326 glLoadTexture(allsurfaces[imgref], imgref);
2327 imgref++;
2328 // store the surface in the text surface cache
2329 if ( !ttfTextHashStore(ttfTextHash, newStr, font, outline, surf) )
2330 {
2331 printlog("warning: failed to store text outline surface with imgref %d\n", imgref - 1);
2332 }
2333 }
2334
2335 // draw the text surface
2336 if ( font == ttf8 )
2337 {
2338 pos.x = x;
2339 pos.y = y - 3;
2340 }
2341 else
2342 {
2343 pos.x = x + 1;
2344 pos.y = y - 4;
2345 }
2346 pos.w = surf->w;
2347 pos.h = surf->h;
2348 drawImageColor(surf, NULL, &pos, color);
2349 pos.x = x;
2350 pos.y = y;
2351
2352 return pos;
2353 }
2354
ttfPrintText(TTF_Font * font,int x,int y,const char * str)2355 SDL_Rect ttfPrintText( TTF_Font* font, int x, int y, const char* str )
2356 {
2357 if ( !str )
2358 {
2359 return errorRect;
2360 }
2361 return ttfPrintTextColor(font, x, y, 0xFFFFFFFF, true, str);
2362 }
2363
2364 /*-------------------------------------------------------------------------------
2365
2366 ttfPrintTextFormatted / ttfPrintTextFormattedColor
2367
2368 Prints a formatted utf8 string to the screen using
2369 ttfPrintText / ttfPrintTextColor
2370
2371 -------------------------------------------------------------------------------*/
2372
ttfPrintTextFormattedColor(TTF_Font * font,int x,int y,Uint32 color,char const * const fmt,...)2373 SDL_Rect ttfPrintTextFormattedColor( TTF_Font* font, int x, int y, Uint32 color, char const * const fmt, ... )
2374 {
2375 char str[1024] = { 0 };
2376
2377 if ( !fmt )
2378 {
2379 return errorRect;
2380 }
2381
2382 // format the string
2383 va_list argptr;
2384 va_start( argptr, fmt );
2385 vsnprintf( str, 1023, fmt, argptr );
2386 va_end( argptr );
2387
2388 // print the text
2389 return ttfPrintTextColor(font, x, y, color, true, str);
2390 }
2391
ttfPrintTextFormatted(TTF_Font * font,int x,int y,char const * const fmt,...)2392 SDL_Rect ttfPrintTextFormatted( TTF_Font* font, int x, int y, char const * const fmt, ... )
2393 {
2394 char str[1024] = { 0 };
2395
2396 if ( !fmt )
2397 {
2398 return errorRect;
2399 }
2400
2401 // format the string
2402 va_list argptr;
2403 va_start( argptr, fmt );
2404 vsnprintf( str, 1023, fmt, argptr );
2405 va_end( argptr );
2406
2407 // print the text
2408 return ttfPrintTextColor(font, x, y, 0xFFFFFFFF, true, str);
2409 }
2410
2411 /*-------------------------------------------------------------------------------
2412
2413 printText
2414
2415 Prints unformatted text to the screen using a font bitmap
2416
2417 -------------------------------------------------------------------------------*/
2418
printText(SDL_Surface * font_bmp,int x,int y,const char * str)2419 void printText( SDL_Surface* font_bmp, int x, int y, const char* str )
2420 {
2421 int c;
2422 int numbytes;
2423 SDL_Rect src, dest, odest;
2424
2425 if ( strlen(str) > 2048 )
2426 {
2427 printlog("error: buffer overflow in printText\n");
2428 return;
2429 }
2430
2431 // format the string
2432 numbytes = strlen(str);
2433
2434 // define font dimensions
2435 dest.x = x;
2436 dest.y = y;
2437 dest.w = font_bmp->w / 16;
2438 src.w = font_bmp->w / 16;
2439 dest.h = font_bmp->h / 16;
2440 src.h = font_bmp->h / 16;
2441
2442 // print the characters in the string
2443 for ( c = 0; c < numbytes; c++ )
2444 {
2445 src.x = (str[c] * src.w) % font_bmp->w;
2446 src.y = (int)((str[c] * src.w) / font_bmp->w) * src.h;
2447 if ( str[c] != 10 && str[c] != 13 ) // LF/CR
2448 {
2449 odest.x = dest.x;
2450 odest.y = dest.y;
2451 drawImage( font_bmp, &src, &dest );
2452 dest.x = odest.x + src.w;
2453 dest.y = odest.y;
2454 }
2455 else if ( str[c] == 10 )
2456 {
2457 dest.x = x;
2458 dest.y += src.h;
2459 }
2460 }
2461 }
2462
2463 /*-------------------------------------------------------------------------------
2464
2465 printTextFormatted
2466
2467 Prints formatted text to the screen using a font bitmap
2468
2469 -------------------------------------------------------------------------------*/
2470
printTextFormatted(SDL_Surface * font_bmp,int x,int y,char const * const fmt,...)2471 void printTextFormatted( SDL_Surface* font_bmp, int x, int y, char const * const fmt, ... )
2472 {
2473 int c;
2474 int numbytes;
2475 char str[1024] = { 0 };
2476 va_list argptr;
2477 SDL_Rect src, dest, odest;
2478
2479 // format the string
2480 va_start( argptr, fmt );
2481 numbytes = vsnprintf( str, 1023, fmt, argptr );
2482 va_end( argptr );
2483
2484 // define font dimensions
2485 dest.x = x;
2486 dest.y = y;
2487 dest.w = font_bmp->w / 16;
2488 src.w = font_bmp->w / 16;
2489 dest.h = font_bmp->h / 16;
2490 src.h = font_bmp->h / 16;
2491
2492 // print the characters in the string
2493 for ( c = 0; c < numbytes; c++ )
2494 {
2495 src.x = (str[c] * src.w) % font_bmp->w;
2496 src.y = (int)((str[c] * src.w) / font_bmp->w) * src.h;
2497 if ( str[c] != 10 && str[c] != 13 ) // LF/CR
2498 {
2499 odest.x = dest.x;
2500 odest.y = dest.y;
2501 drawImage( font_bmp, &src, &dest );
2502 dest.x = odest.x + src.w;
2503 dest.y = odest.y;
2504 }
2505 else if ( str[c] == 10 )
2506 {
2507 dest.x = x;
2508 dest.y += src.h;
2509 }
2510 }
2511 }
2512
2513 /*-------------------------------------------------------------------------------
2514
2515 printTextFormattedAlpha
2516
2517 Prints formatted text to the screen using a font bitmap and taking an
2518 alpha value.
2519
2520 -------------------------------------------------------------------------------*/
2521
printTextFormattedAlpha(SDL_Surface * font_bmp,int x,int y,Uint8 alpha,char const * const fmt,...)2522 void printTextFormattedAlpha(SDL_Surface* font_bmp, int x, int y, Uint8 alpha, char const * const fmt, ...)
2523 {
2524 int c;
2525 int numbytes;
2526 char str[1024] = { 0 };
2527 va_list argptr;
2528 SDL_Rect src, dest, odest;
2529
2530 // format the string
2531 va_start( argptr, fmt );
2532 numbytes = vsnprintf( str, 1023, fmt, argptr );
2533 va_end( argptr );
2534
2535 // define font dimensions
2536 dest.x = x;
2537 dest.y = y;
2538 dest.w = font_bmp->w / 16;
2539 src.w = font_bmp->w / 16;
2540 dest.h = font_bmp->h / 16;
2541 src.h = font_bmp->h / 16;
2542
2543 // print the characters in the string
2544 for ( c = 0; c < numbytes; c++ )
2545 {
2546 src.x = (str[c] * src.w) % font_bmp->w;
2547 src.y = (int)((str[c] * src.w) / font_bmp->w) * src.h;
2548 if ( str[c] != 10 && str[c] != 13 ) // LF/CR
2549 {
2550 odest.x = dest.x;
2551 odest.y = dest.y;
2552 drawImageAlpha( font_bmp, &src, &dest, alpha );
2553 dest.x = odest.x + src.w;
2554 dest.y = odest.y;
2555 }
2556 else if ( str[c] == 10 )
2557 {
2558 dest.x = x;
2559 dest.y += src.h;
2560 }
2561 }
2562 }
2563
2564 /*-------------------------------------------------------------------------------
2565
2566 printTextFormattedColor
2567
2568 Prints formatted text to the screen using a font bitmap and taking a
2569 32-bit color value
2570
2571 -------------------------------------------------------------------------------*/
2572
printTextFormattedColor(SDL_Surface * font_bmp,int x,int y,Uint32 color,char const * const fmt,...)2573 void printTextFormattedColor(SDL_Surface* font_bmp, int x, int y, Uint32 color, char const * const fmt, ...)
2574 {
2575 int c;
2576 int numbytes;
2577 char str[1024] = { 0 };
2578 va_list argptr;
2579 SDL_Rect src, dest, odest;
2580
2581 // format the string
2582 va_start( argptr, fmt );
2583 numbytes = vsnprintf( str, 1023, fmt, argptr );
2584 va_end( argptr );
2585
2586 // define font dimensions
2587 dest.x = x;
2588 dest.y = y;
2589 dest.w = font_bmp->w / 16;
2590 src.w = font_bmp->w / 16;
2591 dest.h = font_bmp->h / 16;
2592 src.h = font_bmp->h / 16;
2593
2594 // print the characters in the string
2595 for ( c = 0; c < numbytes; c++ )
2596 {
2597 src.x = (str[c] * src.w) % font_bmp->w;
2598 src.y = (int)((str[c] * src.w) / font_bmp->w) * src.h;
2599 if ( str[c] != 10 && str[c] != 13 ) // LF/CR
2600 {
2601 odest.x = dest.x;
2602 odest.y = dest.y;
2603 drawImageColor( font_bmp, &src, &dest, color );
2604 dest.x = odest.x + src.w;
2605 dest.y = odest.y;
2606 }
2607 else if ( str[c] == 10 )
2608 {
2609 dest.x = x;
2610 dest.y += src.h;
2611 }
2612 }
2613 }
2614
2615 /*-------------------------------------------------------------------------------
2616
2617 printTextFormattedColor
2618
2619 Prints formatted text to the screen using a font bitmap, while coloring,
2620 rotating, and scaling it
2621
2622 -------------------------------------------------------------------------------*/
2623
printTextFormattedFancy(SDL_Surface * font_bmp,int x,int y,Uint32 color,real_t angle,real_t scale,char * fmt,...)2624 void printTextFormattedFancy(SDL_Surface* font_bmp, int x, int y, Uint32 color, real_t angle, real_t scale, char* fmt, ...)
2625 {
2626 int c;
2627 int numbytes;
2628 char str[1024] = { 0 };
2629 va_list argptr;
2630 SDL_Rect src, dest;
2631
2632 // format the string
2633 va_start( argptr, fmt );
2634 numbytes = vsnprintf( str, 1023, fmt, argptr );
2635 va_end( argptr );
2636
2637 // define font dimensions
2638 real_t newX = x;
2639 real_t newY = y;
2640 dest.w = ((real_t)font_bmp->w / 16.f) * scale;
2641 src.w = font_bmp->w / 16;
2642 dest.h = ((real_t)font_bmp->h / 16.f) * scale;
2643 src.h = font_bmp->h / 16;
2644
2645 // print the characters in the string
2646 int line = 0;
2647 for ( c = 0; c < numbytes; c++ )
2648 {
2649 src.x = (str[c] * src.w) % font_bmp->w;
2650 src.y = (int)((str[c] * src.w) / font_bmp->w) * src.h;
2651 if ( str[c] != 10 && str[c] != 13 ) // LF/CR
2652 {
2653 dest.x = newX;
2654 dest.y = newY;
2655 drawImageFancy( font_bmp, color, angle, &src, &dest );
2656 newX += (real_t)dest.w * cos(angle);
2657 newY += (real_t)dest.h * sin(angle);
2658 }
2659 else if ( str[c] == 10 )
2660 {
2661 line++;
2662 dest.x = x + dest.h * cos(angle + PI / 2) * line;
2663 dest.y = y + dest.h * sin(angle + PI / 2) * line;
2664 }
2665 }
2666 }
2667
2668 /*-------------------------------------------------------------------------------
2669
2670 draws a tooltip
2671
2672 Draws a tooltip box
2673
2674 -------------------------------------------------------------------------------*/
2675
drawTooltip(SDL_Rect * src,Uint32 optionalColor)2676 void drawTooltip(SDL_Rect* src, Uint32 optionalColor)
2677 {
2678 Uint32 color = SDL_MapRGB(mainsurface->format, 0, 192, 255);
2679 if ( optionalColor == 0 )
2680 {
2681 drawRect(src, 0, 250);
2682 }
2683 else
2684 {
2685 color = optionalColor;
2686 }
2687 drawLine(src->x, src->y, src->x + src->w, src->y, color, 255);
2688 drawLine(src->x, src->y + src->h, src->x + src->w, src->y + src->h, color, 255);
2689 drawLine(src->x, src->y, src->x, src->y + src->h, color, 255);
2690 drawLine(src->x + src->w, src->y, src->x + src->w, src->y + src->h, color, 255);
2691 }
2692