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