]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/draw.qc
Merge branch 'master' of git://de.git.xonotic.org/xonotic/xonotic-data.pk3dir
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / draw.qc
1 string draw_mousepointer;
2 vector draw_mousepointer_offset;
3 vector draw_mousepointer_size;
4
5 string draw_UseSkinFor(string pic)
6 {
7         if(substring(pic, 0, 1) == "/")
8                 return substring(pic, 1, strlen(pic)-1);
9         else
10                 return strcat(draw_currentSkin, "/", pic);
11 }
12
13 void draw_setMousePointer(string pic, vector theSize, vector theOffset)
14 {
15         draw_mousepointer = strzone(draw_UseSkinFor(pic));
16         draw_mousepointer_size = theSize;
17         draw_mousepointer_offset = eX * (theOffset_x * theSize_x) + eY * (theOffset_y * theSize_y);
18 }
19
20 void draw_drawMousePointer(vector where)
21 {
22         drawpic(boxToGlobal(where, draw_shift, draw_scale) - draw_mousepointer_offset, draw_mousepointer, draw_mousepointer_size, '1 1 1', draw_alpha, 0);
23 }
24
25 void draw_reset(float cw, float ch, float ox, float oy)
26 {
27         drawfont = FONT_USER+0;
28         draw_shift = '1 0 0' * ox + '0 1 0' * oy;
29         draw_scale = '1 0 0' * cw + '0 1 0' * ch;
30         draw_alpha = 1;
31         draw_fontscale = '1 1 0';
32 }
33
34 vector globalToBox(vector v, vector theOrigin, vector theScale)
35 {
36         v -= theOrigin;
37         v_x /= theScale_x;
38         v_y /= theScale_y;
39         return v;
40 }
41
42 vector globalToBoxSize(vector v, vector theScale)
43 {
44         v_x /= theScale_x;
45         v_y /= theScale_y;
46         return v;
47 }
48
49 vector boxToGlobal(vector v, vector theOrigin, vector theScale)
50 {
51         v_x *= theScale_x;
52         v_y *= theScale_y;
53         v += theOrigin;
54         return v;
55 }
56
57 vector boxToGlobalSize(vector v, vector theScale)
58 {
59         v_x *= theScale_x;
60         v_y *= theScale_y;
61         return v;
62 }
63
64 void draw_PreloadPicture(string pic)
65 {
66         pic = draw_UseSkinFor(pic);
67         precache_pic(pic);
68 }
69
70 void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
71 {
72         if(theSize_x == 0 || theSize_y <= 0) // no default sizing please
73                 return;
74         pic = draw_UseSkinFor(pic);
75         drawpic(boxToGlobal(theOrigin, draw_shift, draw_scale), pic, boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
76 }
77
78 vector draw_PictureSize(string pic)
79 {
80         pic = draw_UseSkinFor(pic);
81         return drawgetimagesize(pic);
82 }
83
84 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
85 {
86         drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
87 }
88
89 // a button picture is a texture containing three parts:
90 //   1/4 width: left part
91 //   1/2 width: middle part (stretched)
92 //   1/4 width: right part
93 // it is assumed to be 4x as wide as high for aspect ratio purposes, which
94 // means, the parts are a square, two squares and a square.
95 void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
96 {
97         vector square;
98         vector width, height;
99         vector bW;
100         pic = draw_UseSkinFor(pic);
101         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
102         theSize = boxToGlobalSize(theSize, draw_scale);
103         theAlpha *= draw_alpha;
104         width = eX * theSize_x;
105         height = eY * theSize_y;
106         if(theSize_x <= theSize_y * 2)
107         {
108                 // button not wide enough
109                 // draw just left and right part then
110                 square = eX * theSize_x * 0.5;
111                 bW = eX * (0.25 * theSize_x / (theSize_y * 2));
112                 drawsubpic(theOrigin,          square + height, pic, '0 0 0', eY + bW, theColor, theAlpha, 0);
113                 drawsubpic(theOrigin + square, square + height, pic, eX - bW, eY + bW, theColor, theAlpha, 0);
114         }
115         else
116         {
117                 square = eX * theSize_y;
118                 drawsubpic(theOrigin,                  height  +     square, pic, '0    0 0', '0.25 1 0', theColor, theAlpha, 0);
119                 drawsubpic(theOrigin +         square, theSize - 2 * square, pic, '0.25 0 0', '0.5  1 0', theColor, theAlpha, 0);
120                 drawsubpic(theOrigin + width - square, height  +     square, pic, '0.75 0 0', '0.25 1 0', theColor, theAlpha, 0);
121         }
122 }
123
124 // a vertical button picture is a texture containing three parts:
125 //   1/4 height: left part
126 //   1/2 height: middle part (stretched)
127 //   1/4 height: right part
128 // it is assumed to be 4x as high as wide for aspect ratio purposes, which
129 // means, the parts are a square, two squares and a square.
130 void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
131 {
132         vector square;
133         vector width, height;
134         vector bH;
135         pic = draw_UseSkinFor(pic);
136         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
137         theSize = boxToGlobalSize(theSize, draw_scale);
138         theAlpha *= draw_alpha;
139         width = eX * theSize_x;
140         height = eY * theSize_y;
141         if(theSize_y <= theSize_x * 2)
142         {
143                 // button not high enough
144                 // draw just upper and lower part then
145                 square = eY * theSize_y * 0.5;
146                 bH = eY * (0.25 * theSize_y / (theSize_x * 2));
147                 drawsubpic(theOrigin,          square + width, pic, '0 0 0', eX + bH, theColor, theAlpha, 0);
148                 drawsubpic(theOrigin + square, square + width, pic, eY - bH, eX + bH, theColor, theAlpha, 0);
149         }
150         else
151         {
152                 square = eY * theSize_x;
153                 drawsubpic(theOrigin,                   width   +     square, pic, '0 0    0', '1 0.25 0', theColor, theAlpha, 0);
154                 drawsubpic(theOrigin +          square, theSize - 2 * square, pic, '0 0.25 0', '1 0.5  0', theColor, theAlpha, 0);
155                 drawsubpic(theOrigin + height - square, width   +     square, pic, '0 0.75 0', '1 0.25 0', theColor, theAlpha, 0);
156         }
157 }
158
159 // a border picture is a texture containing nine parts:
160 //   1/4 width: left part
161 //   1/2 width: middle part (stretched)
162 //   1/4 width: right part
163 // divided into
164 //   1/4 height: top part
165 //   1/2 height: middle part (stretched)
166 //   1/4 height: bottom part
167 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
168 {
169         vector dX, dY;
170         vector width, height;
171         vector bW, bH;
172         pic = draw_UseSkinFor(pic);
173         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
174         theSize = boxToGlobalSize(theSize, draw_scale);
175         theBorderSize = boxToGlobalSize(theBorderSize, draw_scale);
176         theAlpha *= draw_alpha;
177         width = eX * theSize_x;
178         height = eY * theSize_y;
179         // zero size? bail out, we cannot handle this
180         if(theSize_x <= 0 || theSize_y <= 0)
181                 return;
182         if(theBorderSize_x <= 0) // no x border
183         {
184                 if(theBorderSize_y <= 0)
185                 {
186                         drawsubpic(theOrigin,                            width          + height,          pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
187                 }
188                 else if(theSize_y <= theBorderSize_y * 2)
189                 {
190                         // not high enough... draw just top and bottom then
191                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
192                         drawsubpic(theOrigin,                             width          + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
193                         drawsubpic(theOrigin              + height * 0.5, width          + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
194                 }
195                 else
196                 {
197                         dY = theBorderSize_y * eY;
198                         drawsubpic(theOrigin,                            width                   +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
199                         drawsubpic(theOrigin          + dY,              width          + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
200                         drawsubpic(theOrigin + height - dY,              width                   +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
201                 }
202         }
203         else if(theSize_x <= theBorderSize_x * 2)
204         {
205                 // not wide enough... draw just left and right then
206                 bW = eX * (0.25 * theSize_x / (theBorderSize_x * 2));
207                 if(theBorderSize_y <= 0)
208                 {
209                         drawsubpic(theOrigin,                             width * 0.5 + height,          pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
210                         drawsubpic(theOrigin + width * 0.5,               width * 0.5 + height,          pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
211                 }
212                 else if(theSize_y <= theBorderSize_y * 2)
213                 {
214                         // not high enough... draw just corners
215                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
216                         drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
217                         drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
218                         drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
219                         drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
220                 }
221                 else
222                 {
223                         dY = theBorderSize_y * eY;
224                         drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
225                         drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
226                         drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
227                         drawsubpic(theOrigin + width * 0.5          + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
228                         drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
229                         drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5          +     dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
230                 }
231         }
232         else
233         {
234                 if(theBorderSize_y <= 0)
235                 {
236                         dX = theBorderSize_x * eX;
237                         drawsubpic(theOrigin,                                        dX + height,          pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
238                         drawsubpic(theOrigin                       + dX, width - 2 * dX + height,          pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
239                         drawsubpic(theOrigin               + width - dX,             dX + height,          pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
240                 }
241                 else if(theSize_y <= theBorderSize_y * 2)
242                 {
243                         // not high enough... draw just top and bottom then
244                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
245                         dX = theBorderSize_x * eX;
246                         drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
247                         drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
248                         drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
249                         drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
250                         drawsubpic(theOrigin + dX         + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
251                         drawsubpic(theOrigin + width - dX + height * 0.5,             dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
252                 }
253                 else
254                 {
255                         dX = theBorderSize_x * eX;
256                         dY = theBorderSize_y * eY;
257                         drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
258                         drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
259                         drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
260                         drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
261                         drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
262                         drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
263                         drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
264                         drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
265                         drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
266                 }
267         }
268 }
269 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
270 {
271         if(theSize_x <= 0 || theSize_y <= 0)
272                 error("Drawing zero size text?\n");
273
274         //float wi;
275         //wi = draw_TextWidth(theText, ICanHasKallerz, theSize);
276         //draw_Fill(theOrigin, '1 0 0' * wi + '0 1 0' * theSize_y, '1 0 0', 0.3);
277
278         if(ICanHasKallerz)
279                 drawcolorcodedstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theAlpha * draw_alpha, 0);
280         else
281                 drawstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theColor, theAlpha * draw_alpha, 0);
282 }
283 void draw_CenterText(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
284 {
285         //print(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n"));
286         draw_Text(theOrigin - eX * 0.5 * draw_TextWidth(theText, ICanHasKallerz, theSize), theText, theSize, theColor, theAlpha, ICanHasKallerz);
287 }
288
289 float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
290 {
291         //return strlen(theText);
292         //print("draw_TextWidth \"", theText, "\"\n");
293         vector v;
294         v = '0 0 0';
295         //float r;
296         v_x = stringwidth(theText, ICanHasKallerz, globalToBoxSize(boxToGlobalSize(SizeThxBye, draw_scale), draw_fontscale));
297         v = globalToBoxSize(v, draw_scale);
298         return v_x;
299 }
300
301 float draw_clipSet;
302 void draw_SetClip()
303 {
304         if(draw_clipSet)
305                 error("Already clipping, no stack implemented here, sorry");
306         drawsetcliparea(draw_shift_x, draw_shift_y, draw_scale_x, draw_scale_y);
307         draw_clipSet = 1;
308 }
309
310 void draw_SetClipRect(vector theOrigin, vector theScale)
311 {
312         vector o, s;
313         if(draw_clipSet)
314                 error("Already clipping, no stack implemented here, sorry");
315         o = boxToGlobal(theOrigin, draw_shift, draw_scale);
316         s = boxToGlobalSize(theScale, draw_scale);
317         drawsetcliparea(o_x, o_y, s_x, s_y);
318         draw_clipSet = 1;
319 }
320
321 void draw_ClearClip()
322 {
323         if(!draw_clipSet)
324                 error("Not clipping, can't clear it then");
325         drawresetcliparea();
326         draw_clipSet = 0;
327 }
328
329 string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
330 {
331         /*
332         if(draw_TextWidth(theText, ICanHasKallerz, SizeThxBye) <= maxWidth)
333                 return theText;
334         else
335                 return strcat(substring(theText, 0, draw_TextLengthUpToWidth(theText, maxWidth - draw_TextWidth("...", ICanHasKallerz, SizeThxBye), ICanHasKallerz, SizeThxBye)), "...");
336         */
337         if(ICanHasKallerz)
338                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithColors);
339         else
340                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithoutColors);
341 }
342
343 float draw_TextWidth_WithColors(string s, vector theFontSize)
344 {
345         return draw_TextWidth(s, TRUE, theFontSize);
346 }
347
348 float draw_TextWidth_WithoutColors(string s, vector theFontSize)
349 {
350         return draw_TextWidth(s, FALSE, theFontSize);
351 }
352
353 float draw_TextLengthUpToWidth(string theText, float maxWidth, float allowColorCodes, vector theFontSize)
354 {
355         if(allowColorCodes)
356                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithColors);
357         else
358                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithoutColors);
359 }