1 //-----------------------------------------------------------------------------
2 // Overlay
3 //-----------------------------------------------------------------------------
4 
5 #include "overlay.h"
6 #include "console.h"
7 #include "logfile.h"
8 #include "shader.h"
9 #include "render.h"
10 #include "math.h"
11 #include "mem.h"
12 #include "system.h"
13 #include <string.h>
14 
Init(void)15 void Overlay::Init(void)
16 {
17   quads = NULL;
18   elems = NULL;
19   verts = NULL;
20   num_quads = 0;
21   num_elems = 0;
22   num_verts = 0;
23 
24   CreateQuads();
25   CreateElems();
26   CreateVerts();
27 }
28 
Shut(void)29 void Overlay::Shut(void)
30 {
31   if (quads)
32   {
33     for (int i = 0; i < MAX_OVERLAY_QUADS; ++i) quads[i].Shut();
34     delete [] quads;
35   }
36   if (elems) cake_free(elems);
37   if (verts) cake_free(verts);
38   quads = NULL;
39   elems = NULL;
40   verts = NULL;
41 }
42 
Render(ShaderManager * shaders)43 void Overlay::Render(ShaderManager *shaders)
44 {
45   if (!shaders) return;
46 
47   if (num_quads)
48   {
49     Shader *s;
50 
51     int last_shader = -1;
52 
53     gRender->InitializeViewPort();        // set up 2d viewport
54 
55     for (unsigned int i = 0; i < num_quads; ++i)
56     {
57       if (quads[i].shader < 0) continue;
58       if (last_shader != quads[i].shader)
59       {
60         last_shader = quads[i].shader;
61         s = shaders->GetShader(quads[i].shader);
62         gRender->SetRenderState(s);
63       }
64       gRender->PushTriangles(&quads[i]);
65     }
66 
67     num_quads = 0;
68     num_elems = 0;
69     num_verts = 0;
70 
71     gRender->ForceFlush();
72   }
73 }
74 
Quad(int shader,float x,float y,float w,float h,float repx,float repy)75 void Overlay::Quad(int shader, float x, float y, float w, float h, float repx, float repy)
76 {
77   if (MAX_OVERLAY_QUADS <= num_quads + 0 ||
78     MAX_OVERLAY_ELEMS <= num_elems + 6 ||
79     MAX_OVERLAY_VERTS <= num_verts + 4)
80   {
81     //if (gConsole) gConsole->Insertln("^1ERROR: Overlay's buffers are too small.");
82     //else if (gLogFile) gLogFile->Insert("^1ERROR: Overlay's buffers are too small\n");
83     return;   // should stop ?
84   }
85 
86   quads[num_quads].firstelem[0] = elems;
87   quads[num_quads].numelems[0] = 6;
88   quads[num_quads].firstvert[0] = verts + num_verts;
89   quads[num_quads].numverts[0] = 4;
90   quads[num_quads].shader = shader;
91 
92   elems[num_elems + 0] = num_verts + 0;
93   elems[num_elems + 1] = num_verts + 1;
94   elems[num_elems + 2] = num_verts + 2;
95   elems[num_elems + 3] = num_verts + 2;
96   elems[num_elems + 4] = num_verts + 1;
97   elems[num_elems + 5] = num_verts + 3;
98 
99   verts[num_verts + 0].tex_st[0] = 0.0f;
100   verts[num_verts + 0].tex_st[1] = 0.0f;
101   verts[num_verts + 0].colour[0] =
102   verts[num_verts + 0].colour[1] =
103   verts[num_verts + 0].colour[2] =
104   verts[num_verts + 0].colour[3] = 255;
105   verts[num_verts + 0].v_point[0] = x;
106   verts[num_verts + 0].v_point[1] = y;
107   verts[num_verts + 0].v_point[2] = 0;
108 
109   verts[num_verts + 1].tex_st[0] = repx;
110   verts[num_verts + 1].tex_st[1] = 0.0f;
111   verts[num_verts + 1].colour[0] =
112   verts[num_verts + 1].colour[1] =
113   verts[num_verts + 1].colour[2] =
114   verts[num_verts + 1].colour[3] = 255;
115   verts[num_verts + 1].v_point[0] = x + w;
116   verts[num_verts + 1].v_point[1] = y;
117   verts[num_verts + 1].v_point[2] = 0;
118 
119   verts[num_verts + 2].tex_st[0] = 0.0f;
120   verts[num_verts + 2].tex_st[1] = repy;
121   verts[num_verts + 2].colour[0] =
122   verts[num_verts + 2].colour[1] =
123   verts[num_verts + 2].colour[2] =
124   verts[num_verts + 2].colour[3] = 255;
125   verts[num_verts + 2].v_point[0] = x;
126   verts[num_verts + 2].v_point[1] = y + h;
127   verts[num_verts + 2].v_point[2] = 0;
128 
129   verts[num_verts + 3].tex_st[0] = repx;
130   verts[num_verts + 3].tex_st[1] = repy;
131   verts[num_verts + 3].colour[0] =
132   verts[num_verts + 3].colour[1] =
133   verts[num_verts + 3].colour[2] =
134   verts[num_verts + 3].colour[3] = 255;
135   verts[num_verts + 3].v_point[0] = x + w;
136   verts[num_verts + 3].v_point[1] = y + h;
137   verts[num_verts + 3].v_point[2] = 0;
138 
139   num_quads += 1;
140   num_elems += 6;
141   num_verts += 4;
142 }
143 
String(const char * str,int shader,float x,float y,float xsize,float ysize,float rows,float cols,int fontstyle)144 void Overlay::String(const char *str,
145            int shader,
146            float x, float y,
147            float xsize, float ysize,
148            float rows, float cols,
149            int fontstyle)
150 {
151 
152   if (fontstyle & FONT_SHADOWED)
153   {
154     char *shadowstr = new char[strlen(str)+3];
155     sprintf(shadowstr, "^7%s", str);
156 
157     for (char *p = shadowstr+2; strlen(p); ++p)
158     {
159       if (*p == '^' && (*(p+1) >= '0' || *(p+1) <= '9'))
160       {
161         strcpy(p, p+2);
162       }
163     }
164 
165     String(shadowstr, shader, x+2, y+2, xsize, ysize, rows, cols, 0);
166     delete [] shadowstr;
167   }
168 
169   float xnext, xpos, ypos;  // position in the texture (for texture coordinates)
170   int num_chars, color = 0;
171 
172   // Buffer is too small - skip the string creation
173   // Display will be ugly but program shouldn't crash
174   if (MAX_OVERLAY_QUADS <= num_quads) return;
175 
176   num_chars = (int) strlen(str);
177 
178   quads[num_quads].firstelem[0] = elems;
179   quads[num_quads].firstvert[0] = verts + num_verts;
180   quads[num_quads].shader = shader;
181 
182   quads[num_quads].numelems[0] = num_chars*6; // 6 elems for a char
183   quads[num_quads].numverts[0] = num_chars*4; // 4 verts for a char
184 
185   for (int i = 0; i < num_chars; ++i)
186   {
187     if (str[i] == '^')  // color code
188     {
189       ++i;
190       color = str[i] - '0';
191 
192       quads[num_quads].numelems[0] -= 12;
193       quads[num_quads].numverts[0] -= 8;
194       continue;
195     }
196 
197     xpos = ((float) ((str[i]&15)<<4)/256.0f)*cols/16.f;
198     ypos = ((float) ((str[i]>>4)<<4)/256.0f)*rows/16.f;
199     xnext = x + xsize;
200 
201     if (str[i] == ' ')
202     {
203       x = xnext;
204       quads[num_quads].numelems[0] -= 6;
205       quads[num_quads].numverts[0] -= 4;
206       continue;
207     }
208 
209     if (MAX_OVERLAY_ELEMS <= num_elems + 6 ||
210       MAX_OVERLAY_VERTS <= num_verts + 4)
211     {
212       num_elems -= (6*i);
213       num_verts -= (4*i);
214       return;
215     }
216 
217     elems[num_elems + 0] = num_verts + 0;
218     elems[num_elems + 1] = num_verts + 1;
219     elems[num_elems + 2] = num_verts + 2;
220     elems[num_elems + 3] = num_verts + 2;
221     elems[num_elems + 4] = num_verts + 1;
222     elems[num_elems + 5] = num_verts + 3;
223 
224     verts[num_verts + 0].tex_st[0] = xpos;
225     verts[num_verts + 0].tex_st[1] = ypos;
226     ColorCopy(text_colors[color], verts[num_verts + 0].colour);
227     verts[num_verts + 0].v_point[0] = x;
228     verts[num_verts + 0].v_point[1] = y;
229     verts[num_verts + 0].v_point[2] = 0;
230 
231     verts[num_verts + 1].tex_st[0] = xpos + (cols-1)/256.0f;
232     verts[num_verts + 1].tex_st[1] = ypos;
233     ColorCopy(text_colors[color], verts[num_verts + 1].colour);
234     verts[num_verts + 1].v_point[0] = xnext;
235     verts[num_verts + 1].v_point[1] = y;
236     verts[num_verts + 1].v_point[2] = 0;
237 
238     verts[num_verts + 2].tex_st[0] = xpos;
239     verts[num_verts + 2].tex_st[1] = ypos + rows/256.0f;
240     ColorCopy(text_colors[color], verts[num_verts + 2].colour);
241     verts[num_verts + 2].v_point[0] = x;
242     verts[num_verts + 2].v_point[1] = y + ysize;
243     verts[num_verts + 2].v_point[2] = 0;
244 
245     verts[num_verts + 3].tex_st[0] = xpos + (cols-1)/256.0f;
246     verts[num_verts + 3].tex_st[1] = ypos + rows/256.0f;
247     ColorCopy(text_colors[color], verts[num_verts + 3].colour);
248     verts[num_verts + 3].v_point[0] = xnext;
249     verts[num_verts + 3].v_point[1] = y + ysize;
250     verts[num_verts + 3].v_point[2] = 0;
251 
252     x = xnext;
253     num_elems += 6;
254     num_verts += 4;
255   }
256 
257   num_quads += 1;
258 }
259 
CreateVerts(void)260 void Overlay::CreateVerts(void)
261 {
262   verts = (vertex_t*) cake_malloc(MAX_OVERLAY_VERTS*sizeof(vertex_t), "Overlay::CreateVerts.verts");
263 
264   if (!verts) ThrowException(ALLOCATION_ERROR, "Overlay::CreateVerts");
265 
266   // Initialize the new vertice
267   for (int i = 0; i < MAX_OVERLAY_VERTS; ++i)
268   {
269     VectorClear(verts[i].v_point);
270     VectorClear(verts[i].v_norm);
271     ColorClear(verts[i].colour);
272     TexcoordClear(verts[i].tex_st);
273     TexcoordClear(verts[i].lm_st);
274   }
275 }
276 
CreateQuads(void)277 void Overlay::CreateQuads(void)
278 {
279   quads = new Surface[MAX_OVERLAY_QUADS];
280 
281   if (!quads) ThrowException(ALLOCATION_ERROR, "Overlay::CreateQuads");
282 
283   // Initialize the new quads
284   for (int i = 0; i < MAX_OVERLAY_QUADS; ++i) quads[i].Init();
285 }
286 
CreateElems(void)287 void Overlay::CreateElems(void)
288 {
289   elems = (int*) cake_malloc(MAX_OVERLAY_ELEMS*sizeof(int), "Overlay::CreateElems.elems");
290 
291   if (!elems) ThrowException(ALLOCATION_ERROR, "Overlay::CreateElems");
292 
293   // Initialize the new elems
294   for (int i = 0; i < MAX_OVERLAY_ELEMS; ++i) elems[i] = 0;
295 }
296