1 #include "gui2_element.h"
2 #include "main.h"
3
GuiElement(GuiContainer * owner,const string & id)4 GuiElement::GuiElement(GuiContainer* owner, const string& id)
5 : position_alignment(ATopLeft), owner(owner), rect(0, 0, 0, 0), visible(true), enabled(true), hover(false), focus(false), active(false), id(id)
6 {
7 owner->elements.push_back(this);
8 destroyed = false;
9 }
10
~GuiElement()11 GuiElement::~GuiElement()
12 {
13 if (owner)
14 {
15 LOG(ERROR) << "GuiElement was destroyed while it still had an owner...";
16 }
17 }
18
onMouseDown(sf::Vector2f position)19 bool GuiElement::onMouseDown(sf::Vector2f position)
20 {
21 return false;
22 }
23
onMouseDrag(sf::Vector2f position)24 void GuiElement::onMouseDrag(sf::Vector2f position)
25 {
26 }
27
onMouseUp(sf::Vector2f position)28 void GuiElement::onMouseUp(sf::Vector2f position)
29 {
30 }
31
onKey(sf::Event::KeyEvent key,int unicode)32 bool GuiElement::onKey(sf::Event::KeyEvent key, int unicode)
33 {
34 return false;
35 }
36
onHotkey(const HotkeyResult & key)37 void GuiElement::onHotkey(const HotkeyResult& key)
38 {
39 }
40
onJoystickAxis(const AxisAction & axisAction)41 bool GuiElement::onJoystickAxis(const AxisAction& axisAction)
42 {
43 return false;
44 }
45
setSize(sf::Vector2f size)46 GuiElement* GuiElement::setSize(sf::Vector2f size)
47 {
48 this->size = size;
49 return this;
50 }
51
setSize(float x,float y)52 GuiElement* GuiElement::setSize(float x, float y)
53 {
54 this->size.x = x;
55 this->size.y = y;
56 return this;
57 }
58
getSize() const59 sf::Vector2f GuiElement::getSize() const
60 {
61 return size;
62 }
63
setMargins(float n)64 GuiElement* GuiElement::setMargins(float n)
65 {
66 margins.left = margins.top = margins.width = margins.height = n;
67 return this;
68 }
69
setMargins(float x,float y)70 GuiElement* GuiElement::setMargins(float x, float y)
71 {
72 margins.left = margins.width = x;
73 margins.top = margins.height = y;
74 return this;
75 }
76
setMargins(float left,float top,float right,float bottom)77 GuiElement* GuiElement::setMargins(float left, float top, float right, float bottom)
78 {
79 margins.left = left;
80 margins.top = top;
81 margins.width = right;
82 margins.height = bottom;
83 return this;
84 }
85
setPosition(float x,float y,EGuiAlign alignment)86 GuiElement* GuiElement::setPosition(float x, float y, EGuiAlign alignment)
87 {
88 this->position.x = x;
89 this->position.y = y;
90 this->position_alignment = alignment;
91 return this;
92 }
93
setPosition(sf::Vector2f position,EGuiAlign alignment)94 GuiElement* GuiElement::setPosition(sf::Vector2f position, EGuiAlign alignment)
95 {
96 this->position = position;
97 this->position_alignment = alignment;
98 return this;
99 }
100
getPositionOffset() const101 sf::Vector2f GuiElement::getPositionOffset() const
102 {
103 return position;
104 }
105
setVisible(bool visible)106 GuiElement* GuiElement::setVisible(bool visible)
107 {
108 this->visible = visible;
109 return this;
110 }
111
hide()112 GuiElement* GuiElement::hide()
113 {
114 setVisible(false);
115 return this;
116 }
117
show()118 GuiElement* GuiElement::show()
119 {
120 setVisible(true);
121 return this;
122 }
123
isVisible() const124 bool GuiElement::isVisible() const
125 {
126 return visible;
127 }
128
setEnable(bool enable)129 GuiElement* GuiElement::setEnable(bool enable)
130 {
131 this->enabled = enable;
132 return this;
133 }
134
enable()135 GuiElement* GuiElement::enable()
136 {
137 setEnable(true);
138 return this;
139 }
140
disable()141 GuiElement* GuiElement::disable()
142 {
143 setEnable(false);
144 return this;
145 }
146
isEnabled() const147 bool GuiElement::isEnabled() const
148 {
149 return enabled;
150 }
151
setActive(bool active)152 GuiElement* GuiElement::setActive(bool active)
153 {
154 this->active = active;
155 return this;
156 }
157
isActive() const158 bool GuiElement::isActive() const
159 {
160 return active;
161 }
162
moveToFront()163 void GuiElement::moveToFront()
164 {
165 if (owner)
166 {
167 owner->elements.remove(this);
168 owner->elements.push_back(this);
169 }
170 }
171
moveToBack()172 void GuiElement::moveToBack()
173 {
174 if (owner)
175 {
176 owner->elements.remove(this);
177 owner->elements.push_front(this);
178 }
179 }
180
getCenterPoint() const181 sf::Vector2f GuiElement::getCenterPoint() const
182 {
183 return sf::Vector2f(rect.left + rect.width / 2.0, rect.top + rect.height / 2.0);
184 }
185
getOwner()186 GuiContainer* GuiElement::getOwner()
187 {
188 return owner;
189 }
190
getTopLevelContainer()191 GuiContainer* GuiElement::getTopLevelContainer()
192 {
193 GuiContainer* top_level = owner;
194 while(dynamic_cast<GuiElement*>(top_level) != nullptr)
195 top_level = dynamic_cast<GuiElement*>(top_level)->getOwner();
196 return top_level;
197 }
198
destroy()199 void GuiElement::destroy()
200 {
201 destroyed = true;
202 }
203
isDestroyed()204 bool GuiElement::isDestroyed()
205 {
206 return destroyed;
207 }
208
updateRect(sf::FloatRect parent_rect)209 void GuiElement::updateRect(sf::FloatRect parent_rect)
210 {
211 sf::Vector2f local_size = size;
212 if (local_size.x == GuiSizeMax)
213 local_size.x = parent_rect.width - fabs(position.x);
214 if (local_size.y == GuiSizeMax)
215 local_size.y = parent_rect.height - fabs(position.y);
216
217 if (local_size.x == GuiSizeMatchHeight)
218 local_size.x = local_size.y;
219 if (local_size.y == GuiSizeMatchWidth)
220 local_size.y = local_size.x;
221
222 local_size.x -= margins.width + margins.left;
223 local_size.y -= margins.height + margins.top;
224
225 switch(position_alignment)
226 {
227 case ATopLeft:
228 case ACenterLeft:
229 case ABottomLeft:
230 rect.left = parent_rect.left + position.x + margins.left;
231 break;
232 case ATopCenter:
233 case ACenter:
234 case ABottomCenter:
235 rect.left = parent_rect.left + parent_rect.width / 2.0 + position.x - local_size.x / 2.0;
236 break;
237 case ATopRight:
238 case ACenterRight:
239 case ABottomRight:
240 rect.left = parent_rect.left + parent_rect.width + position.x - local_size.x - margins.width;
241 break;
242 }
243
244 switch(position_alignment)
245 {
246 case ATopLeft:
247 case ATopRight:
248 case ATopCenter:
249 rect.top = parent_rect.top + position.y + margins.top;
250 break;
251 case ACenterLeft:
252 case ACenterRight:
253 case ACenter:
254 rect.top = parent_rect.top + parent_rect.height / 2.0 + position.y - local_size.y / 2.0;
255 break;
256 case ABottomLeft:
257 case ABottomRight:
258 case ABottomCenter:
259 rect.top = parent_rect.top + parent_rect.height + position.y - local_size.y - margins.height;
260 break;
261 }
262
263 rect.width = local_size.x;
264 rect.height = local_size.y;
265 if (rect.width < 0)
266 {
267 rect.left += rect.width;
268 rect.width = -rect.width;
269 }
270 if (rect.height < 0)
271 {
272 rect.top += rect.height;
273 rect.height = -rect.height;
274 }
275 }
276
277 [[nodiscard]]
adjustRenderTexture(sf::RenderTexture & texture)278 bool GuiElement::adjustRenderTexture(sf::RenderTexture& texture)
279 {
280 #ifdef SFML_SYSTEM_ANDROID
281 /* On GL ES systems, SFML runs on assumptions regarding
282 the available GL extensions, for instance considering packed depth/stencil is never available.[1]
283 Because of that unreliability, just forego render textures on those systems.
284
285 [1]: https://github.com/SFML/SFML/blob/2f11710abc5aa478503a7ff3f9e654bd2078ebab/src/SFML/Graphics/GLExtensions.hpp#L128
286 */
287 return false;
288 #else
289 auto success = true;
290 P<WindowManager> window_manager = engine->getObject("windowManager");
291
292 //Hack the rectangle for this element so it sits perfectly on pixel boundaries.
293 auto pixel_coords = window_manager->mapCoordsToPixel(sf::Vector2f(rect.width, rect.height));
294
295 sf::Vector2u texture_size{ static_cast<uint32_t>(pixel_coords.x), static_cast<uint32_t>(pixel_coords.y) };
296 if (texture.getSize() != texture_size)
297 {
298 sf::ContextSettings settings{};
299 settings.stencilBits = 8;
300 success = texture.create(texture_size.x, texture_size.y, settings);
301 }
302
303 if (success)
304 {
305 //Set the view so it covers this elements normal rect. So we can draw exactly the same on this texture as no the normal screen.
306 texture.setView(sf::View{ rect });
307 }
308
309 return success;
310 #endif
311 }
312
drawRenderTexture(sf::RenderTexture & texture,sf::RenderTarget & window,sf::Color color,const sf::RenderStates & states)313 void GuiElement::drawRenderTexture(sf::RenderTexture& texture, sf::RenderTarget& window, sf::Color color, const sf::RenderStates& states)
314 {
315 texture.display();
316
317 sf::Sprite sprite(texture.getTexture());
318
319 sprite.setColor(color);
320 sprite.setPosition(rect.left, rect.top);
321
322 const auto& texture_size = texture.getSize();
323 const auto& texture_viewport = texture.getView().getViewport();
324 sprite.setScale(rect.width / float(texture_size.x * texture_viewport.width), rect.height / float(texture_size.y * texture_viewport.height));
325
326 window.draw(sprite, states);
327 }
328
drawText(sf::RenderTarget & window,sf::FloatRect rect,const string & text,EGuiAlign align,float font_size,sf::Font * font,sf::Color color)329 void GuiElement::drawText(sf::RenderTarget& window, sf::FloatRect rect, const string& text, EGuiAlign align, float font_size, sf::Font* font, sf::Color color)
330 {
331 sf::Text textElement(sf::String::fromUtf8(std::begin(text), std::end(text)), *font, font_size);
332 float y = 0;
333 float x = 0;
334
335 //The "base line" of the text draw is the "Y position where the text is drawn" + font_size.
336 //The height of normal text is 70% of the font_size.
337 //So use those properties to align the text. Depending on the localbounds does not work.
338 switch(align)
339 {
340 case ATopLeft:
341 case ATopRight:
342 case ATopCenter:
343 y = rect.top - 0.3 * font_size;
344 break;
345 case ABottomLeft:
346 case ABottomRight:
347 case ABottomCenter:
348 y = rect.top + rect.height - font_size;
349 break;
350 case ACenterLeft:
351 case ACenterRight:
352 case ACenter:
353 y = rect.top + rect.height / 2.0 - font_size + font_size * 0.35;
354 break;
355 }
356
357 switch(align)
358 {
359 case ATopLeft:
360 case ABottomLeft:
361 case ACenterLeft:
362 x = rect.left - textElement.getLocalBounds().left;
363 break;
364 case ATopRight:
365 case ABottomRight:
366 case ACenterRight:
367 x = rect.left + rect.width - textElement.getLocalBounds().width - textElement.getLocalBounds().left;
368 break;
369 case ATopCenter:
370 case ABottomCenter:
371 case ACenter:
372 x = rect.left + rect.width / 2.0 - textElement.getLocalBounds().width / 2.0 - textElement.getLocalBounds().left;
373 break;
374 }
375 textElement.setPosition(x, y);
376 textElement.setColor(color);
377 window.draw(textElement);
378 }
379
drawVerticalText(sf::RenderTarget & window,sf::FloatRect rect,const string & text,EGuiAlign align,float font_size,sf::Font * font,sf::Color color)380 void GuiElement::drawVerticalText(sf::RenderTarget& window, sf::FloatRect rect, const string& text, EGuiAlign align, float font_size, sf::Font* font, sf::Color color)
381 {
382 sf::Text textElement(sf::String::fromUtf8(std::begin(text), std::end(text)), *font, font_size);
383 textElement.setRotation(-90);
384 float x = 0;
385 float y = 0;
386 x = rect.left + rect.width / 2.0 - textElement.getLocalBounds().height / 2.0 - textElement.getLocalBounds().top;
387 switch(align)
388 {
389 case ATopLeft:
390 case ABottomLeft:
391 case ACenterLeft:
392 y = rect.top + rect.height;
393 break;
394 case ATopRight:
395 case ABottomRight:
396 case ACenterRight:
397 y = rect.top + textElement.getLocalBounds().left + textElement.getLocalBounds().width;
398 break;
399 case ATopCenter:
400 case ABottomCenter:
401 case ACenter:
402 y = rect.top + rect.height / 2.0 + textElement.getLocalBounds().width / 2.0 + textElement.getLocalBounds().left;
403 break;
404 }
405 textElement.setPosition(x, y);
406 textElement.setColor(color);
407 window.draw(textElement);
408 }
409
draw9Cut(sf::RenderTarget & window,sf::FloatRect rect,const string & texture,sf::Color color,float width_factor)410 void GuiElement::draw9Cut(sf::RenderTarget& window, sf::FloatRect rect, const string& texture, sf::Color color, float width_factor)
411 {
412 sf::Sprite sprite;
413 textureManager.setTexture(sprite, texture);
414 sf::IntRect textureSize = sprite.getTextureRect();
415 int cornerSizeT = textureSize.height / 3;
416 float cornerSizeR = cornerSizeT;
417 float scale = 1.0;
418 if (cornerSizeT > rect.height / 2)
419 {
420 scale = float(rect.height / 2) / cornerSizeR;
421 sprite.setScale(scale, scale);
422 cornerSizeR *= scale;
423 }else if (cornerSizeT > rect.width / 2)
424 {
425 scale = float(rect.width / 2) / cornerSizeR;
426 sprite.setScale(scale, scale);
427 cornerSizeR *= scale;
428 }
429
430 sprite.setColor(color);
431 sprite.setOrigin(0, 0);
432
433 float w = 1.0;
434 if (cornerSizeR > rect.width * width_factor)
435 w = rect.width * width_factor / cornerSizeR;
436
437 //TopLeft
438 sprite.setPosition(rect.left, rect.top);
439 sprite.setTextureRect(sf::IntRect(0, 0, cornerSizeT * w, cornerSizeT));
440 window.draw(sprite);
441 //BottomLeft
442 sprite.setPosition(rect.left, rect.top + rect.height - cornerSizeR);
443 sprite.setTextureRect(sf::IntRect(0, textureSize.height - cornerSizeT, cornerSizeT * w, cornerSizeT));
444 window.draw(sprite);
445
446 if (rect.height > cornerSizeR * 2)
447 {
448 //left
449 sprite.setPosition(rect.left, rect.top + cornerSizeR);
450 sprite.setTextureRect(sf::IntRect(0, cornerSizeT, cornerSizeT * w, 1));
451 sprite.setScale(scale, rect.height - cornerSizeR*2);
452 window.draw(sprite);
453 sprite.setScale(scale, scale);
454 }
455 if (w < 1.0)
456 return;
457
458 if (rect.width - cornerSizeR > rect.width * width_factor)
459 w = (width_factor - cornerSizeR / rect.width) * (rect.width / (rect.width - cornerSizeR * 2));
460
461 if (rect.width > cornerSizeR * 2)
462 {
463 //Top
464 sprite.setPosition(rect.left + cornerSizeR, rect.top);
465 sprite.setTextureRect(sf::IntRect(cornerSizeT, 0, textureSize.width - cornerSizeT * 2, cornerSizeT));
466 sprite.setScale((rect.width - cornerSizeR*2) / float(textureSize.width - cornerSizeT * 2) * w, scale);
467 window.draw(sprite);
468 //Bottom
469 sprite.setPosition(rect.left + cornerSizeR, rect.top + rect.height - cornerSizeR);
470 sprite.setTextureRect(sf::IntRect(cornerSizeT, textureSize.height - cornerSizeT, textureSize.width - cornerSizeT * 2, cornerSizeT));
471 sprite.setScale((rect.width - cornerSizeR*2) / float(textureSize.width - cornerSizeT * 2) * w, scale);
472 window.draw(sprite);
473 sprite.setScale(scale, scale);
474 }
475
476 if (rect.width > cornerSizeR * 2 && rect.height > cornerSizeR * 2)
477 {
478 //Center
479 sprite.setPosition(rect.left + cornerSizeR, rect.top + cornerSizeR);
480 sprite.setTextureRect(sf::IntRect(cornerSizeT, cornerSizeT, 1, 1));
481 sprite.setScale((rect.width - cornerSizeR*2) * w, rect.height - cornerSizeR*2);
482 window.draw(sprite);
483 sprite.setScale(scale, scale);
484 }
485 if (w < 1.0)
486 return;
487 if (width_factor < 1.0)
488 w = (width_factor - (rect.width - cornerSizeR) / rect.width) * (rect.width / cornerSizeR);
489
490 //TopRight
491 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top);
492 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, 0, cornerSizeT * w, cornerSizeT));
493 window.draw(sprite);
494 //BottomRight
495 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top + rect.height - cornerSizeR);
496 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, textureSize.height - cornerSizeT, cornerSizeT * w, cornerSizeT));
497 window.draw(sprite);
498
499 if (rect.height > cornerSizeR * 2)
500 {
501 //Right
502 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top + cornerSizeR);
503 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, cornerSizeT, cornerSizeT * w, 1));
504 sprite.setScale(scale, rect.height - cornerSizeR*2);
505 window.draw(sprite);
506 }
507 }
508
draw9CutV(sf::RenderTarget & window,sf::FloatRect rect,const string & texture,sf::Color color,float height_factor)509 void GuiElement::draw9CutV(sf::RenderTarget& window, sf::FloatRect rect, const string& texture, sf::Color color, float height_factor)
510 {
511 sf::Sprite sprite;
512 textureManager.setTexture(sprite, texture);
513 sf::IntRect textureSize = sprite.getTextureRect();
514 int cornerSizeT = textureSize.height / 3;
515 float cornerSizeR = cornerSizeT;
516 float scale = 1.0;
517 if (cornerSizeT > rect.height / 2)
518 {
519 scale = float(rect.height / 2) / cornerSizeR;
520 sprite.setScale(scale, scale);
521 cornerSizeR *= scale;
522 }else if (cornerSizeT > rect.width / 2)
523 {
524 scale = float(rect.width / 2) / cornerSizeR;
525 sprite.setScale(scale, scale);
526 cornerSizeR *= scale;
527 }
528
529 sprite.setColor(color);
530 sprite.setOrigin(0, 0);
531
532 float h = 1.0;
533 if (cornerSizeR > rect.height * height_factor)
534 h = rect.height * height_factor / cornerSizeR;
535
536 //BottomLeft
537 sprite.setPosition(rect.left, rect.top + rect.height - cornerSizeR * h);
538 sprite.setTextureRect(sf::IntRect(0, textureSize.height - cornerSizeT * h, cornerSizeT, cornerSizeT * h));
539 window.draw(sprite);
540 //BottomRight
541 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top + rect.height - cornerSizeR * h);
542 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, textureSize.height - cornerSizeT * h, cornerSizeT, cornerSizeT * h));
543 window.draw(sprite);
544
545 if (rect.width > cornerSizeR * 2)
546 {
547 //Bottom
548 sprite.setPosition(rect.left + cornerSizeR, rect.top + rect.height - cornerSizeR * h);
549 sprite.setTextureRect(sf::IntRect(cornerSizeT, textureSize.height - cornerSizeT * h, textureSize.width - cornerSizeT * 2, cornerSizeT * h));
550 sprite.setScale((rect.width - cornerSizeR*2) / float(textureSize.width - cornerSizeT * 2), scale);
551 window.draw(sprite);
552 sprite.setScale(scale, scale);
553 }
554
555 if (h < 1.0)
556 return;
557
558 if (rect.height - cornerSizeR > rect.height * height_factor)
559 h = (height_factor - cornerSizeR / rect.height) * (rect.height / (rect.height - cornerSizeR * 2));
560
561 if (rect.height > cornerSizeR * 2)
562 {
563 //left
564 sprite.setPosition(rect.left, rect.top + cornerSizeR + (rect.height - cornerSizeR * 2) * (1.0f - h));
565 sprite.setTextureRect(sf::IntRect(0, cornerSizeT, cornerSizeT, 1));
566 sprite.setScale(scale, (rect.height - cornerSizeR*2) * h);
567 window.draw(sprite);
568 sprite.setScale(scale, scale);
569 //Right
570 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top + cornerSizeR + (rect.height - cornerSizeR * 2) * (1.0f - h));
571 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, cornerSizeT, cornerSizeT, 1));
572 sprite.setScale(scale, (rect.height - cornerSizeR*2) * h);
573 window.draw(sprite);
574 }
575
576 if (rect.width > cornerSizeR * 2 && rect.height > cornerSizeR * 2)
577 {
578 //Center
579 sprite.setPosition(rect.left + cornerSizeR, rect.top + cornerSizeR + (rect.height - cornerSizeR * 2) * (1.0f - h));
580 sprite.setTextureRect(sf::IntRect(cornerSizeT, cornerSizeT, 1, 1));
581 sprite.setScale(rect.width - cornerSizeR*2, (rect.height - cornerSizeR*2) * h);
582 window.draw(sprite);
583 sprite.setScale(scale, scale);
584 }
585
586 if (h < 1.0)
587 return;
588 if (height_factor < 1.0)
589 h = (height_factor - (rect.height - cornerSizeR) / rect.height) * (rect.height / cornerSizeR);
590
591 //TopLeft
592 sprite.setPosition(rect.left, rect.top + cornerSizeR * (1.0 - h));
593 sprite.setTextureRect(sf::IntRect(0, cornerSizeT * (1.0 - h), cornerSizeT, cornerSizeT * h));
594 window.draw(sprite);
595 //TopRight
596 sprite.setPosition(rect.left + rect.width - cornerSizeR, rect.top + cornerSizeR * (1.0 - h));
597 sprite.setTextureRect(sf::IntRect(textureSize.width - cornerSizeT, cornerSizeT * (1.0 - h), cornerSizeT, cornerSizeT * h));
598 window.draw(sprite);
599
600 if (rect.height > cornerSizeR * 2)
601 {
602 //Top
603 sprite.setPosition(rect.left + cornerSizeR, rect.top + cornerSizeR * (1.0 - h));
604 sprite.setTextureRect(sf::IntRect(cornerSizeT, cornerSizeT * (1.0 - h), 1, cornerSizeT * h));
605 sprite.setScale(rect.width - cornerSizeR*2, scale);
606 window.draw(sprite);
607 }
608 }
609
drawStretched(sf::RenderTarget & window,sf::FloatRect rect,const string & texture,sf::Color color)610 void GuiElement::drawStretched(sf::RenderTarget& window, sf::FloatRect rect, const string& texture, sf::Color color)
611 {
612 if (rect.width >= rect.height)
613 {
614 drawStretchedH(window, rect, texture, color);
615 }else{
616 drawStretchedV(window, rect, texture, color);
617 }
618 }
619
drawStretchedH(sf::RenderTarget & window,sf::FloatRect rect,const string & texture,sf::Color color)620 void GuiElement::drawStretchedH(sf::RenderTarget& window, sf::FloatRect rect, const string& texture, sf::Color color)
621 {
622 sf::Texture* texture_ptr = textureManager.getTexture(texture);
623 sf::Vector2f texture_size = sf::Vector2f(texture_ptr->getSize());
624 sf::VertexArray a(sf::TrianglesStrip, 8);
625
626 float w = rect.height / 2.0f;
627 if (w * 2 > rect.width)
628 w = rect.width / 2.0f;
629 a[0].position = sf::Vector2f(rect.left, rect.top);
630 a[1].position = sf::Vector2f(rect.left, rect.top + rect.height);
631 a[2].position = sf::Vector2f(rect.left + w, rect.top);
632 a[3].position = sf::Vector2f(rect.left + w, rect.top + rect.height);
633 a[4].position = sf::Vector2f(rect.left + rect.width - w, rect.top);
634 a[5].position = sf::Vector2f(rect.left + rect.width - w, rect.top + rect.height);
635 a[6].position = sf::Vector2f(rect.left + rect.width, rect.top);
636 a[7].position = sf::Vector2f(rect.left + rect.width, rect.top + rect.height);
637
638 a[0].texCoords = sf::Vector2f(0, 0);
639 a[1].texCoords = sf::Vector2f(0, texture_size.y);
640 a[2].texCoords = sf::Vector2f(texture_size.x / 2, 0);
641 a[3].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y);
642 a[4].texCoords = sf::Vector2f(texture_size.x / 2, 0);
643 a[5].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y);
644 a[6].texCoords = sf::Vector2f(texture_size.x, 0);
645 a[7].texCoords = sf::Vector2f(texture_size.x, texture_size.y);
646
647 for(int n=0; n<8; n++)
648 a[n].color = color;
649
650 window.draw(a, texture_ptr);
651 }
652
drawStretchedV(sf::RenderTarget & window,sf::FloatRect rect,const string & texture,sf::Color color)653 void GuiElement::drawStretchedV(sf::RenderTarget& window, sf::FloatRect rect, const string& texture, sf::Color color)
654 {
655 sf::Texture* texture_ptr = textureManager.getTexture(texture);
656 sf::Vector2f texture_size = sf::Vector2f(texture_ptr->getSize());
657 sf::VertexArray a(sf::TrianglesStrip, 8);
658
659 float h = rect.width / 2.0;
660 if (h * 2 > rect.height)
661 h = rect.height / 2.0f;
662 a[0].position = sf::Vector2f(rect.left, rect.top);
663 a[1].position = sf::Vector2f(rect.left + rect.width, rect.top);
664 a[2].position = sf::Vector2f(rect.left, rect.top + h);
665 a[3].position = sf::Vector2f(rect.left + rect.width, rect.top + h);
666 a[4].position = sf::Vector2f(rect.left, rect.top + rect.height - h);
667 a[5].position = sf::Vector2f(rect.left + rect.width, rect.top + rect.height - h);
668 a[6].position = sf::Vector2f(rect.left, rect.top + rect.height);
669 a[7].position = sf::Vector2f(rect.left + rect.width, rect.top + rect.height);
670
671 a[0].texCoords = sf::Vector2f(0, 0);
672 a[1].texCoords = sf::Vector2f(0, texture_size.y);
673 a[2].texCoords = sf::Vector2f(texture_size.x / 2, 0);
674 a[3].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y);
675 a[4].texCoords = sf::Vector2f(texture_size.x / 2, 0);
676 a[5].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y);
677 a[6].texCoords = sf::Vector2f(texture_size.x, 0);
678 a[7].texCoords = sf::Vector2f(texture_size.x, texture_size.y);
679
680 for(int n=0; n<8; n++)
681 a[n].color = color;
682
683 window.draw(a, texture_ptr);
684 }
685
drawStretchedHV(sf::RenderTarget & window,sf::FloatRect rect,float corner_size,const string & texture,sf::Color color)686 void GuiElement::drawStretchedHV(sf::RenderTarget& window, sf::FloatRect rect, float corner_size, const string& texture, sf::Color color)
687 {
688 sf::Texture* texture_ptr = textureManager.getTexture(texture);
689 sf::Vector2f texture_size = sf::Vector2f(texture_ptr->getSize());
690 sf::VertexArray a(sf::TrianglesStrip, 8);
691
692 for(int n=0; n<8; n++)
693 a[n].color = color;
694
695 corner_size = std::min(corner_size, rect.height / 2.0f);
696 corner_size = std::min(corner_size, rect.width / 2.0f);
697
698 a[0].position = sf::Vector2f(rect.left, rect.top);
699 a[1].position = sf::Vector2f(rect.left, rect.top + corner_size);
700 a[2].position = sf::Vector2f(rect.left + corner_size, rect.top);
701 a[3].position = sf::Vector2f(rect.left + corner_size, rect.top + corner_size);
702 a[4].position = sf::Vector2f(rect.left + rect.width - corner_size, rect.top);
703 a[5].position = sf::Vector2f(rect.left + rect.width - corner_size, rect.top + corner_size);
704 a[6].position = sf::Vector2f(rect.left + rect.width, rect.top);
705 a[7].position = sf::Vector2f(rect.left + rect.width, rect.top + corner_size);
706
707 a[0].texCoords = sf::Vector2f(0, 0);
708 a[1].texCoords = sf::Vector2f(0, texture_size.y / 2.0);
709 a[2].texCoords = sf::Vector2f(texture_size.x / 2, 0);
710 a[3].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y / 2.0);
711 a[4].texCoords = sf::Vector2f(texture_size.x / 2, 0);
712 a[5].texCoords = sf::Vector2f(texture_size.x / 2, texture_size.y / 2.0);
713 a[6].texCoords = sf::Vector2f(texture_size.x, 0);
714 a[7].texCoords = sf::Vector2f(texture_size.x, texture_size.y / 2.0);
715
716 window.draw(a, texture_ptr);
717
718 a[0].position.y = rect.top + rect.height - corner_size;
719 a[2].position.y = rect.top + rect.height - corner_size;
720 a[4].position.y = rect.top + rect.height - corner_size;
721 a[6].position.y = rect.top + rect.height - corner_size;
722
723 a[0].texCoords.y = texture_size.y / 2.0;
724 a[2].texCoords.y = texture_size.y / 2.0;
725 a[4].texCoords.y = texture_size.y / 2.0;
726 a[6].texCoords.y = texture_size.y / 2.0;
727
728 window.draw(a, texture_ptr);
729
730 a[1].position.y = rect.top + rect.height;
731 a[3].position.y = rect.top + rect.height;
732 a[5].position.y = rect.top + rect.height;
733 a[7].position.y = rect.top + rect.height;
734
735 a[1].texCoords.y = texture_size.y;
736 a[3].texCoords.y = texture_size.y;
737 a[5].texCoords.y = texture_size.y;
738 a[7].texCoords.y = texture_size.y;
739
740 window.draw(a, texture_ptr);
741 }
742
drawArrow(sf::RenderTarget & window,sf::FloatRect rect,sf::Color color,float rotation)743 void GuiElement::drawArrow(sf::RenderTarget& window, sf::FloatRect rect, sf::Color color, float rotation)
744 {
745 sf::Sprite arrow;
746 textureManager.setTexture(arrow, "gui/SelectorArrow");
747 arrow.setPosition(rect.left + rect.width / 2.0, rect.top + rect.height / 2.0);
748 float f = rect.height / float(arrow.getTextureRect().height);
749 arrow.setScale(f, f);
750 arrow.setRotation(rotation);
751 arrow.setColor(color);
752 window.draw(arrow);
753 }
754
selectColor(ColorSet & color_set) const755 sf::Color GuiElement::selectColor(ColorSet& color_set) const
756 {
757 if (!enabled)
758 return color_set.disabled;
759 if (active)
760 return color_set.active;
761 if (hover)
762 return color_set.hover;
763 if (focus)
764 return color_set.focus;
765 return color_set.normal;
766 }
767
doLineWrap(const string & text,float font_size,float width)768 GuiElement::LineWrapResult GuiElement::doLineWrap(const string& text, float font_size, float width)
769 {
770 LineWrapResult result;
771 result.text = text;
772 result.line_count = 1;
773 {
774 float currentOffset = 0;
775 bool first_word = true;
776 std::size_t wordBegining = 0;
777
778 for (std::size_t pos(0); pos < result.text.length(); ++pos)
779 {
780 char currentChar = result.text[pos];
781 if (currentChar == '\n')
782 {
783 currentOffset = 0;
784 first_word = true;
785 result.line_count += 1;
786 continue;
787 }
788 else if (currentChar == ' ')
789 {
790 wordBegining = pos;
791 first_word = false;
792 }
793
794 sf::Glyph glyph = main_font->getGlyph(currentChar, font_size, false);
795 currentOffset += glyph.advance;
796
797 if (!first_word && currentOffset > width)
798 {
799 pos = wordBegining;
800 result.text[pos] = '\n';
801 first_word = true;
802 currentOffset = 0;
803 result.line_count += 1;
804 }
805 }
806 }
807 return result;
808 }
809