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