2 #include "../common/util.qh"
3 #include "../common/constants.qh"
5 string draw_mousepointer;
6 vector draw_mousepointer_offset;
7 vector draw_mousepointer_size;
9 void draw_setMousePointer(string pic, vector theSize, vector theOffset)
11 draw_mousepointer = strzone(draw_UseSkinFor(pic));
12 draw_mousepointer_size = theSize;
13 draw_mousepointer_offset = eX * (theOffset.x * theSize.x) + eY * (theOffset.y * theSize.y);
16 void draw_drawMousePointer(vector where)
18 drawpic(boxToGlobal(where, draw_shift, draw_scale) - draw_mousepointer_offset, draw_mousepointer, draw_mousepointer_size, '1 1 1', draw_alpha, 0);
21 void draw_reset(float cw, float ch, float ox, float oy)
23 draw_shift = '1 0 0' * ox + '0 1 0' * oy;
24 draw_scale = '1 0 0' * cw + '0 1 0' * ch;
26 draw_fontscale = '1 1 0';
30 void draw_beginBoldFont()
32 drawfont = FONT_USER+3;
35 void draw_endBoldFont()
37 drawfont = FONT_USER+0;
40 vector globalToBox(vector v, vector theOrigin, vector theScale)
48 vector globalToBoxSize(vector v, vector theScale)
55 vector boxToGlobal(vector v, vector theOrigin, vector theScale)
63 vector boxToGlobalSize(vector v, vector theScale)
70 string draw_PreloadPicture(string pic)
72 pic = draw_UseSkinFor(pic);
73 return precache_pic(pic);
76 string draw_PreloadPictureWithFlags(string pic, float f)
78 pic = draw_UseSkinFor(pic);
79 return precache_pic(pic, f);
82 void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
84 if(theSize.x == 0 || theSize.y <= 0) // no default sizing please
86 pic = draw_UseSkinFor(pic);
87 drawpic(boxToGlobal(theOrigin, draw_shift, draw_scale), pic, boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
90 vector draw_PictureSize(string pic)
92 pic = draw_UseSkinFor(pic);
93 return drawgetimagesize(pic);
96 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
98 drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
101 // a button picture is a texture containing three parts:
102 // 1/4 width: left part
103 // 1/2 width: middle part (stretched)
104 // 1/4 width: right part
105 // it is assumed to be 4x as wide as high for aspect ratio purposes, which
106 // means, the parts are a square, two squares and a square.
107 void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
110 vector width, height;
112 pic = draw_UseSkinFor(pic);
113 theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
114 theSize = boxToGlobalSize(theSize, draw_scale);
115 theAlpha *= draw_alpha;
116 width = eX * theSize.x;
117 height = eY * theSize.y;
118 if(theSize.x <= theSize.y * 2)
120 // button not wide enough
121 // draw just left and right part then
122 square = eX * theSize.x * 0.5;
123 bW = eX * (0.25 * theSize.x / (theSize.y * 2));
124 drawsubpic(theOrigin, square + height, pic, '0 0 0', eY + bW, theColor, theAlpha, 0);
125 drawsubpic(theOrigin + square, square + height, pic, eX - bW, eY + bW, theColor, theAlpha, 0);
129 square = eX * theSize.y;
130 drawsubpic(theOrigin, height + square, pic, '0 0 0', '0.25 1 0', theColor, theAlpha, 0);
131 drawsubpic(theOrigin + square, theSize - 2 * square, pic, '0.25 0 0', '0.5 1 0', theColor, theAlpha, 0);
132 drawsubpic(theOrigin + width - square, height + square, pic, '0.75 0 0', '0.25 1 0', theColor, theAlpha, 0);
136 // a vertical button picture is a texture containing three parts:
137 // 1/4 height: left part
138 // 1/2 height: middle part (stretched)
139 // 1/4 height: right part
140 // it is assumed to be 4x as high as wide for aspect ratio purposes, which
141 // means, the parts are a square, two squares and a square.
142 void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
145 vector width, height;
147 pic = draw_UseSkinFor(pic);
148 theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
149 theSize = boxToGlobalSize(theSize, draw_scale);
150 theAlpha *= draw_alpha;
151 width = eX * theSize.x;
152 height = eY * theSize.y;
153 if(theSize.y <= theSize.x * 2)
155 // button not high enough
156 // draw just upper and lower part then
157 square = eY * theSize.y * 0.5;
158 bH = eY * (0.25 * theSize.y / (theSize.x * 2));
159 drawsubpic(theOrigin, square + width, pic, '0 0 0', eX + bH, theColor, theAlpha, 0);
160 drawsubpic(theOrigin + square, square + width, pic, eY - bH, eX + bH, theColor, theAlpha, 0);
164 square = eY * theSize.x;
165 drawsubpic(theOrigin, width + square, pic, '0 0 0', '1 0.25 0', theColor, theAlpha, 0);
166 drawsubpic(theOrigin + square, theSize - 2 * square, pic, '0 0.25 0', '1 0.5 0', theColor, theAlpha, 0);
167 drawsubpic(theOrigin + height - square, width + square, pic, '0 0.75 0', '1 0.25 0', theColor, theAlpha, 0);
171 // a border picture is a texture containing nine parts:
172 // 1/4 width: left part
173 // 1/2 width: middle part (stretched)
174 // 1/4 width: right part
176 // 1/4 height: top part
177 // 1/2 height: middle part (stretched)
178 // 1/4 height: bottom part
179 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
182 vector width, height;
184 pic = draw_UseSkinFor(pic);
185 theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
186 theSize = boxToGlobalSize(theSize, draw_scale);
187 theBorderSize = boxToGlobalSize(theBorderSize, draw_scale);
188 theAlpha *= draw_alpha;
189 width = eX * theSize.x;
190 height = eY * theSize.y;
191 // zero size? bail out, we cannot handle this
192 if(theSize.x <= 0 || theSize.y <= 0)
194 if(theBorderSize.x <= 0) // no x border
196 if(theBorderSize.y <= 0)
198 drawsubpic(theOrigin, width + height, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
200 else if(theSize.y <= theBorderSize.y * 2)
202 // not high enough... draw just top and bottom then
203 bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
204 drawsubpic(theOrigin, width + height * 0.5, pic, '0.25 0 0', '0.5 0 0' + bH, theColor, theAlpha, 0);
205 drawsubpic(theOrigin + height * 0.5, width + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5 0 0' + bH, theColor, theAlpha, 0);
209 dY = theBorderSize.y * eY;
210 drawsubpic(theOrigin, width + dY, pic, '0.25 0 0', '0.5 0.25 0', theColor, theAlpha, 0);
211 drawsubpic(theOrigin + dY, width + height - 2 * dY, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
212 drawsubpic(theOrigin + height - dY, width + dY, pic, '0.25 0.75 0', '0.5 0.25 0', theColor, theAlpha, 0);
215 else if(theSize.x <= theBorderSize.x * 2)
217 // not wide enough... draw just left and right then
218 bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
219 if(theBorderSize.y <= 0)
221 drawsubpic(theOrigin, width * 0.5 + height, pic, '0 0.25 0', '0 0.5 0' + bW, theColor, theAlpha, 0);
222 drawsubpic(theOrigin + width * 0.5, width * 0.5 + height, pic, '0 0.25 0' + eX - bW, '0 0.5 0' + bW, theColor, theAlpha, 0);
224 else if(theSize.y <= theBorderSize.y * 2)
226 // not high enough... draw just corners
227 bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
228 drawsubpic(theOrigin, width * 0.5 + height * 0.5, pic, '0 0 0', bW + bH, theColor, theAlpha, 0);
229 drawsubpic(theOrigin + width * 0.5, width * 0.5 + height * 0.5, pic, eX - bW, bW + bH, theColor, theAlpha, 0);
230 drawsubpic(theOrigin + height * 0.5, width * 0.5 + height * 0.5, pic, eY - bH, bW + bH, theColor, theAlpha, 0);
231 drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
235 dY = theBorderSize.y * eY;
236 drawsubpic(theOrigin, width * 0.5 + dY, pic, '0 0 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
237 drawsubpic(theOrigin + width * 0.5, width * 0.5 + dY, pic, '0 0 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
238 drawsubpic(theOrigin + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0', '0 0.5 0' + bW, theColor, theAlpha, 0);
239 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);
240 drawsubpic(theOrigin + height - dY, width * 0.5 + dY, pic, '0 0.75 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
241 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);
246 if(theBorderSize.y <= 0)
248 dX = theBorderSize.x * eX;
249 drawsubpic(theOrigin, dX + height, pic, '0 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
250 drawsubpic(theOrigin + dX, width - 2 * dX + height, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
251 drawsubpic(theOrigin + width - dX, dX + height, pic, '0.75 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
253 else if(theSize.y <= theBorderSize.y * 2)
255 // not high enough... draw just top and bottom then
256 bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
257 dX = theBorderSize.x * eX;
258 drawsubpic(theOrigin, dX + height * 0.5, pic, '0 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
259 drawsubpic(theOrigin + dX, width - 2 * dX + height * 0.5, pic, '0.25 0 0', '0.5 0 0' + bH, theColor, theAlpha, 0);
260 drawsubpic(theOrigin + width - dX, dX + height * 0.5, pic, '0.75 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
261 drawsubpic(theOrigin + height * 0.5, dX + height * 0.5, pic, '0 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
262 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);
263 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);
267 dX = theBorderSize.x * eX;
268 dY = theBorderSize.y * eY;
269 drawsubpic(theOrigin, dX + dY, pic, '0 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
270 drawsubpic(theOrigin + dX, width - 2 * dX + dY, pic, '0.25 0 0', '0.5 0.25 0', theColor, theAlpha, 0);
271 drawsubpic(theOrigin + width - dX, dX + dY, pic, '0.75 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
272 drawsubpic(theOrigin + dY, dX + height - 2 * dY, pic, '0 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
273 drawsubpic(theOrigin + dY + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
274 drawsubpic(theOrigin + dY + width - dX, dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
275 drawsubpic(theOrigin + height - dY, dX + dY, pic, '0 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
276 drawsubpic(theOrigin + height - dY + dX, width - 2 * dX + dY, pic, '0.25 0.75 0', '0.5 0.25 0', theColor, theAlpha, 0);
277 drawsubpic(theOrigin + height - dY + width - dX, dX + dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
281 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
283 if(theSize.x <= 0 || theSize.y <= 0) {
284 LOG_TRACE("Drawing zero size text?\n");
289 //wi = draw_TextWidth(theText, ICanHasKallerz, theSize);
290 //draw_Fill(theOrigin, '1 0 0' * wi + '0 1 0' * theSize_y, '1 0 0', 0.3);
293 drawcolorcodedstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theAlpha * draw_alpha, 0);
295 drawstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theColor, theAlpha * draw_alpha, 0);
297 void draw_CenterText(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
299 //dprint(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n"));
300 draw_Text(theOrigin - eX * 0.5 * draw_TextWidth(theText, ICanHasKallerz, theSize), theText, theSize, theColor, theAlpha, ICanHasKallerz);
303 float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
305 //return strlen(theText);
306 //dprint("draw_TextWidth \"", theText, "\"\n");
310 v.x = stringwidth(theText, ICanHasKallerz, globalToBoxSize(boxToGlobalSize(SizeThxBye, draw_scale), draw_fontscale));
311 v = globalToBoxSize(v, draw_scale);
315 float draw_CondensedFontFactor(string theText, float ICanHasKallerz, vector SizeThxBye, float maxWidth)
317 float w = draw_TextWidth(theText, ICanHasKallerz, SizeThxBye);
319 //dprintf("NOTE: label text %s too wide for label, condensed by factor %f\n", theText, maxWidth / w);
329 error("Already clipping, no stack implemented here, sorry");
330 drawsetcliparea(draw_shift.x, draw_shift.y, draw_scale.x, draw_scale.y);
334 void draw_SetClipRect(vector theOrigin, vector theScale)
338 error("Already clipping, no stack implemented here, sorry");
339 o = boxToGlobal(theOrigin, draw_shift, draw_scale);
340 s = boxToGlobalSize(theScale, draw_scale);
341 drawsetcliparea(o.x, o.y, s.x, s.y);
345 void draw_ClearClip()
348 error("Not clipping, can't clear it then");
353 string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
356 if(draw_TextWidth(theText, ICanHasKallerz, SizeThxBye) <= maxWidth)
359 return strcat(substring(theText, 0, draw_TextLengthUpToWidth(theText, maxWidth - draw_TextWidth("...", ICanHasKallerz, SizeThxBye), ICanHasKallerz, SizeThxBye)), "...");
362 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithColors);
364 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithoutColors);
367 float draw_TextWidth_WithColors(string s, vector theFontSize)
369 return draw_TextWidth(s, true, theFontSize);
372 float draw_TextWidth_WithoutColors(string s, vector theFontSize)
374 return draw_TextWidth(s, false, theFontSize);
377 float draw_TextLengthUpToWidth(string theText, float maxWidth, float allowColorCodes, vector theFontSize)
380 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithColors);
382 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithoutColors);