]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/draw.qc
now PROPERLY apply draw_fontscale in TextWidth
[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         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         if(theSize_x <= theBorderSize_x * 2)
178         {
179                 // not wide enough... draw just left and right then
180                 bW = eX * (0.25 * theSize_x / (theBorderSize_x * 2));
181                 if(theSize_y <= theBorderSize_y * 2)
182                 {
183                         // not high enough... draw just corners
184                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
185                         drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
186                         drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
187                         drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
188                         drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
189                 }
190                 else
191                 {
192                         dY = theBorderSize_x * eY;
193                         drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
194                         drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
195                         drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
196                         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);
197                         drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
198                         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);
199                 }
200         }
201         else
202         {
203                 if(theSize_y <= theBorderSize_y * 2)
204                 {
205                         // not high enough... draw just top and bottom then
206                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
207                         dX = theBorderSize_x * eX;
208                         drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
209                         drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
210                         drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
211                         drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
212                         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);
213                         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);
214                 }
215                 else
216                 {
217                         dX = theBorderSize_x * eX;
218                         dY = theBorderSize_x * eY;
219                         drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
220                         drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
221                         drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
222                         drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
223                         drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
224                         drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
225                         drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
226                         drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
227                         drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
228                 }
229         }
230 }
231 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
232 {
233         if(theSize_x <= 0 || theSize_y <= 0)
234                 error("Drawing zero size text?\n");
235
236         //float wi;
237         //wi = draw_TextWidth(theText, ICanHasKallerz, theSize);
238         //draw_Fill(theOrigin, '1 0 0' * wi + '0 1 0' * theSize_y, '1 0 0', 0.3);
239
240         if(ICanHasKallerz)
241                 drawcolorcodedstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theAlpha * draw_alpha, 0);
242         else
243                 drawstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theColor, theAlpha * draw_alpha, 0);
244 }
245 void draw_CenterText(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
246 {
247         //print(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n"));
248         draw_Text(theOrigin - eX * 0.5 * draw_TextWidth(theText, ICanHasKallerz, theSize), theText, theSize, theColor, theAlpha, ICanHasKallerz);
249 }
250
251 float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
252 {
253         //return strlen(theText);
254         //print("draw_TextWidth \"", theText, "\"\n");
255         vector v;
256         v = '0 0 0';
257         //float r;
258         v_x = stringwidth(theText, ICanHasKallerz, globalToBoxSize(boxToGlobalSize(SizeThxBye, draw_scale), draw_fontscale));
259         v = globalToBoxSize(v, draw_scale);
260         return v_x;
261 }
262
263 float draw_clipSet;
264 void draw_SetClip()
265 {
266         if(draw_clipSet)
267                 error("Already clipping, no stack implemented here, sorry");
268         drawsetcliparea(draw_shift_x, draw_shift_y, draw_scale_x, draw_scale_y);
269         draw_clipSet = 1;
270 }
271
272 void draw_SetClipRect(vector theOrigin, vector theScale)
273 {
274         vector o, s;
275         if(draw_clipSet)
276                 error("Already clipping, no stack implemented here, sorry");
277         o = boxToGlobal(theOrigin, draw_shift, draw_scale);
278         s = boxToGlobalSize(theScale, draw_scale);
279         drawsetcliparea(o_x, o_y, s_x, s_y);
280         draw_clipSet = 1;
281 }
282
283 void draw_ClearClip()
284 {
285         if(!draw_clipSet)
286                 error("Not clipping, can't clear it then");
287         drawresetcliparea();
288         draw_clipSet = 0;
289 }
290
291 string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
292 {
293         /*
294         if(draw_TextWidth(theText, ICanHasKallerz, SizeThxBye) <= maxWidth)
295                 return theText;
296         else
297                 return strcat(substring(theText, 0, draw_TextLengthUpToWidth(theText, maxWidth - draw_TextWidth("...", ICanHasKallerz, SizeThxBye), ICanHasKallerz, SizeThxBye)), "...");
298         */
299         if(ICanHasKallerz)
300                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithColors);
301         else
302                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithoutColors);
303 }
304
305 float draw_TextWidth_WithColors(string s, vector theFontSize)
306 {
307         return draw_TextWidth(s, TRUE, theFontSize);
308 }
309
310 float draw_TextWidth_WithoutColors(string s, vector theFontSize)
311 {
312         return draw_TextWidth(s, FALSE, theFontSize);
313 }
314
315 float draw_TextLengthUpToWidth(string theText, float maxWidth, float allowColorCodes, vector theFontSize)
316 {
317         if(allowColorCodes)
318                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithColors);
319         else
320                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithoutColors);
321 }