854 lines
22 KiB
C++
854 lines
22 KiB
C++
/* --------------------------------------------------------------------
|
|
EXTREME TUXRACER
|
|
|
|
Copyright (C) 1999-2001 Jasmin F. Patry (Tuxracer)
|
|
Copyright (C) 2010 Extreme Tuxracer Team
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
---------------------------------------------------------------------*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <etr_config.h>
|
|
#endif
|
|
|
|
#include "gui.h"
|
|
#include "textures.h"
|
|
#include "font.h"
|
|
#include "ogl.h"
|
|
#include "winsys.h"
|
|
#include <vector>
|
|
|
|
|
|
#define CURSOR_SIZE 10
|
|
|
|
static std::vector<TWidget*> Widgets;
|
|
static int lock_focussed = -1;
|
|
static int focussed = -1;
|
|
static bool locked_LR = false;
|
|
static bool locked_UD = false;
|
|
|
|
static TWidget* AddWidget(TWidget* widget) {
|
|
if (Widgets.size() == focussed) {
|
|
widget->focus = true;
|
|
widget->Focussed();
|
|
}
|
|
Widgets.push_back(widget);
|
|
return widget;
|
|
}
|
|
|
|
static bool Inside(int x, int y, const TRect& Rect) {
|
|
return (x >= Rect.left
|
|
&& x <= Rect.left + Rect.width
|
|
&& y >= Rect.top
|
|
&& y <= Rect.top + Rect.height);
|
|
}
|
|
|
|
TWidget::TWidget(int x, int y, int width, int height, bool interactive_)
|
|
: active(true)
|
|
, visible(true)
|
|
, interactive(interactive_)
|
|
, focus(false) {
|
|
mouseRect.top = y;
|
|
mouseRect.left = x;
|
|
mouseRect.height = height;
|
|
mouseRect.width = width;
|
|
position.x = x;
|
|
position.y = y;
|
|
}
|
|
|
|
bool TWidget::Click(int x, int y) {
|
|
return active && visible && Inside(x, y, mouseRect);
|
|
}
|
|
|
|
void TWidget::MouseMove(int x, int y) {
|
|
bool ofocus = focus;
|
|
focus = interactive && active && visible && Inside(x, y, mouseRect);
|
|
if (ofocus != focus)
|
|
Focussed();
|
|
}
|
|
|
|
|
|
TLabel::TLabel(const sf::String& string, int x, int y, const sf::Color& color)
|
|
: TWidget(x, y, 0, 0, false)
|
|
, text(string, FT.getCurrentFont(), FT.GetSize()) {
|
|
if (x == CENTER)
|
|
text.setPosition((Winsys.resolution.width - text.getLocalBounds().width) / 2, y);
|
|
else
|
|
text.setPosition(x, y);
|
|
text.setFillColor(color);
|
|
text.setOutlineColor(color);
|
|
}
|
|
|
|
void TLabel::Focussed(bool masterFocus) {
|
|
focus = masterFocus && active;
|
|
if (focus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
} else {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
|
|
void TLabel::Draw() const {
|
|
Winsys.draw(text);
|
|
}
|
|
|
|
sf::Vector2f TLabel::GetSize() const {
|
|
return sf::Vector2f(text.getLocalBounds().width, text.getLocalBounds().height);
|
|
|
|
}
|
|
|
|
TLabel* AddLabel(const sf::String& string, int x, int y, const sf::Color& color) {
|
|
return static_cast<TLabel*>(AddWidget(new TLabel(string, x, y, color)));
|
|
}
|
|
|
|
|
|
TFramedText::TFramedText(int x, int y, int width, int height, int line, const sf::Color& backcol, const sf::String& string, unsigned int ftsize, bool borderFocus_)
|
|
: TWidget(x, y, width, height, false)
|
|
, frame(sf::Vector2f(width - line * 2, height - line * 2))
|
|
, text(string, FT.getCurrentFont(), ftsize)
|
|
, borderFocus(borderFocus_) {
|
|
text.setPosition(x + line + 20, y + line);
|
|
if (!borderFocus) {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
} else {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
}
|
|
frame.setPosition(x + line, y + line);
|
|
frame.setOutlineThickness(line);
|
|
frame.setFillColor(backcol);
|
|
frame.setOutlineColor(colWhite);
|
|
}
|
|
|
|
void TFramedText::Activated() {
|
|
if (!active) {
|
|
text.setFillColor(colLGrey);
|
|
text.setOutlineColor(colLGrey);
|
|
} else if (borderFocus || focus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
} else {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
|
|
void TFramedText::Focussed(bool masterFocus) {
|
|
focus = masterFocus && active;
|
|
if (focus) {
|
|
frame.setOutlineColor(colDYell);
|
|
if (!borderFocus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
}
|
|
} else {
|
|
frame.setOutlineColor(colWhite);
|
|
if (!borderFocus) {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TFramedText::Draw() const {
|
|
Winsys.draw(frame);
|
|
Winsys.draw(text);
|
|
}
|
|
|
|
TFramedText* AddFramedText(int x, int y, int width, int height, int line, const sf::Color& backcol, const sf::String& text, unsigned int ftsize, bool borderFocus) {
|
|
return static_cast<TFramedText*>(AddWidget(new TFramedText(x, y, width, height, line, backcol, text, ftsize, borderFocus)));
|
|
}
|
|
|
|
TTextButton::TTextButton(int x, int y, const sf::String& text_, int ftsize)
|
|
: TWidget(x, y, 0, 0)
|
|
, text(text_, FT.getCurrentFont(), ftsize) {
|
|
if (ftsize < 0) text.setCharacterSize(FT.AutoSizeN(4));
|
|
|
|
int len = text.getLocalBounds().width;
|
|
if (x == CENTER) position.x = (Winsys.resolution.width - len) / 2;
|
|
text.setPosition(position.x, position.y);
|
|
int offs = ftsize / 5;
|
|
mouseRect.left = position.x-20;
|
|
mouseRect.top = position.y+offs;
|
|
mouseRect.width = len+40;
|
|
mouseRect.height = ftsize+offs;
|
|
}
|
|
|
|
void TTextButton::Focussed() {
|
|
if (focus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
} else {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
|
|
void TTextButton::Draw() const {
|
|
Winsys.draw(text);
|
|
}
|
|
|
|
TTextButton* AddTextButton(const sf::String& text, int x, int y, int ftsize) {
|
|
return static_cast<TTextButton*>(AddWidget(new TTextButton(x, y, text, ftsize)));
|
|
}
|
|
|
|
TTextButton* AddTextButtonN(const sf::String& text, int x, int y, int rel_ftsize) {
|
|
unsigned int siz = FT.AutoSizeN(rel_ftsize);
|
|
return AddTextButton(text, x, y, siz);
|
|
}
|
|
|
|
|
|
TTextField::TTextField(int x, int y, int width, int height, const sf::String& text_)
|
|
: TWidget(x, y, width, height)
|
|
, text(text_, FT.getCurrentFont(), FT.AutoSizeN(5))
|
|
, frame(sf::Vector2f(width-6.f, height-6.f))
|
|
, cursorShape(sf::Vector2f(2.f, 30.f * Winsys.scale))
|
|
, maxLng(32)
|
|
, time(0.0)
|
|
, cursor(false) {
|
|
text.setPosition(mouseRect.left + 20, mouseRect.top);
|
|
cursorShape.setFillColor(colYellow);
|
|
frame.setPosition(x + 3, y + 3);
|
|
frame.setOutlineThickness(3);
|
|
frame.setFillColor(colMBackgr);
|
|
frame.setOutlineColor(colWhite);
|
|
SetCursorPos(0);
|
|
}
|
|
|
|
void TTextField::Draw() const {
|
|
Winsys.draw(frame);
|
|
Winsys.draw(text);
|
|
if (cursor && focus)
|
|
Winsys.draw(cursorShape);
|
|
}
|
|
|
|
void TTextField::TextEnter(char c) {
|
|
if (c != '\b') {
|
|
sf::String string = text.getString();
|
|
string.insert(cursorPos, c);
|
|
text.setString(string);
|
|
SetCursorPos(cursorPos+1);
|
|
}
|
|
}
|
|
|
|
void TTextField::SetCursorPos(std::size_t new_pos) {
|
|
cursorPos = new_pos;
|
|
cursorShape.setPosition(text.findCharacterPos(cursorPos).x, mouseRect.top + 9);
|
|
}
|
|
|
|
void TTextField::Focussed() {
|
|
if (focus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
frame.setOutlineColor(colDYell);
|
|
} else {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
frame.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
|
|
bool TTextField::Click(int x, int y) {
|
|
if (TWidget::Click(x, y)) {
|
|
cursorPos = 0;
|
|
float first = text.findCharacterPos(cursorPos).x;
|
|
for (;;) {
|
|
float second = text.findCharacterPos(cursorPos + 1).x;
|
|
if ((first + second) / 2.f >= x || cursorPos >= text.getString().getSize())
|
|
break;
|
|
cursorPos++;
|
|
first = second;
|
|
}
|
|
cursorShape.setPosition(text.findCharacterPos(cursorPos).x, mouseRect.top + 9);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void eraseFromText(sf::Text& text, std::size_t pos) {
|
|
sf::String str = text.getString();
|
|
str.erase(pos, 1);
|
|
text.setString(str);
|
|
}
|
|
void TTextField::Key(sf::Keyboard::Key key, bool released) {
|
|
switch (key) {
|
|
case sf::Keyboard::Delete:
|
|
if (cursorPos < text.getString().getSize()) eraseFromText(text, cursorPos);
|
|
break;
|
|
case sf::Keyboard::BackSpace:
|
|
if (cursorPos > 0) { eraseFromText(text, cursorPos-1); SetCursorPos(cursorPos - 1); }
|
|
break;
|
|
case sf::Keyboard::Right:
|
|
if (cursorPos < text.getString().getSize()) SetCursorPos(cursorPos + 1);
|
|
break;
|
|
case sf::Keyboard::Left:
|
|
if (cursorPos > 0) SetCursorPos(cursorPos - 1);
|
|
break;
|
|
case sf::Keyboard::Home:
|
|
SetCursorPos(0);
|
|
break;
|
|
case sf::Keyboard::End:
|
|
SetCursorPos(text.getString().getSize());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TTextField::UpdateCursor(float timestep) {
|
|
time += timestep;
|
|
if (time > CRSR_PERIODE) {
|
|
time = 0;
|
|
cursor = !cursor;
|
|
}
|
|
}
|
|
|
|
TTextField* AddTextField(const sf::String& text, int x, int y, int width, int height) {
|
|
locked_LR = true;
|
|
return static_cast<TTextField*>(AddWidget(new TTextField(x, y, width, height, text)));
|
|
}
|
|
|
|
TCheckbox::TCheckbox(int x, int y, int width, const sf::String& tag_)
|
|
: TWidget(x, y, 32 * Winsys.scale / 0.8f, 32 * Winsys.scale / 0.8f)
|
|
, text(tag_, FT.getCurrentFont(), FT.GetSize())
|
|
, back(Tex.GetSFTexture(CHECKBOX))
|
|
, checkmark(Tex.GetSFTexture(CHECKMARK_SMALL))
|
|
, checked(false) {
|
|
text.setPosition(x, y);
|
|
back.setPosition(x + width - 32, y);
|
|
checkmark.setPosition(x + width - 32, y);
|
|
mouseRect.left = x + width - 32;
|
|
back.setScale(Winsys.scale / 0.8f, Winsys.scale / 0.8f);
|
|
checkmark.setScale(Winsys.scale / 0.8f, Winsys.scale / 0.8f);
|
|
}
|
|
|
|
void TCheckbox::SetPosition(int x, int y) {
|
|
text.setPosition(x, y);
|
|
back.setPosition(x, y);
|
|
checkmark.setPosition(x, y);
|
|
}
|
|
|
|
void TCheckbox::Focussed() {
|
|
if (focus) {
|
|
text.setFillColor(colDYell);
|
|
text.setOutlineColor(colDYell);
|
|
} else {
|
|
text.setFillColor(colWhite);
|
|
text.setOutlineColor(colWhite);
|
|
}
|
|
}
|
|
|
|
void TCheckbox::Draw() const {
|
|
Winsys.draw(back);
|
|
if (checked)
|
|
Winsys.draw(checkmark);
|
|
Winsys.draw(text);
|
|
}
|
|
|
|
bool TCheckbox::Click(int x, int y) {
|
|
if (active && visible && Inside(x, y, mouseRect)) {
|
|
checked = !checked;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TCheckbox::Key(sf::Keyboard::Key key, bool released) {
|
|
if (released) return;
|
|
|
|
if (key == sf::Keyboard::Space || key == sf::Keyboard::Return) {
|
|
checked = !checked;
|
|
}
|
|
}
|
|
|
|
TCheckbox* AddCheckbox(int x, int y, int width, const sf::String& tag) {
|
|
return static_cast<TCheckbox*>(AddWidget(new TCheckbox(x, y, width, tag)));
|
|
}
|
|
|
|
TIconButton::TIconButton(int x, int y, const sf::Texture& texture, float size_, int max_, int value_)
|
|
: TWidget(x, y, 32, 32)
|
|
, sprite(texture)
|
|
, frame(sf::Vector2f(size_, size_))
|
|
, size(size_)
|
|
, maximum(max_)
|
|
, value(value_) {
|
|
sprite.setScale(size / (texture.getSize().x / 2.f), size / (texture.getSize().y / 2.f));
|
|
sprite.setPosition(x, y);
|
|
frame.setPosition(x, y);
|
|
frame.setOutlineColor(colWhite);
|
|
frame.setOutlineThickness(3.f);
|
|
SetValue(value_);
|
|
}
|
|
|
|
void TIconButton::SetValue(int _value) {
|
|
value = _value;
|
|
if (value > maximum)
|
|
value = 0;
|
|
else if (value < 0)
|
|
value = maximum;
|
|
|
|
sf::Vector2u texSize = sprite.getTexture()->getSize();
|
|
switch (value) {
|
|
case 0:
|
|
sprite.setTextureRect(sf::IntRect(0, 0, texSize.x / 2, texSize.y / 2));
|
|
break;
|
|
case 1:
|
|
sprite.setTextureRect(sf::IntRect(texSize.x / 2, 0, texSize.x / 2, texSize.y / 2));
|
|
break;
|
|
case 2:
|
|
sprite.setTextureRect(sf::IntRect(0, texSize.y / 2, texSize.x / 2, texSize.y / 2));
|
|
break;
|
|
case 3:
|
|
sprite.setTextureRect(sf::IntRect(texSize.x / 2, texSize.y / 2, texSize.x / 2, texSize.y / 2));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TIconButton::Draw() const {
|
|
Winsys.draw(frame);
|
|
Winsys.draw(sprite);
|
|
}
|
|
|
|
void TIconButton::Focussed() {
|
|
if (focus)
|
|
frame.setOutlineColor(colDYell);
|
|
else
|
|
frame.setOutlineColor(colWhite);
|
|
}
|
|
|
|
bool TIconButton::Click(int x, int y) {
|
|
if (Inside(x, y, mouseRect)) {
|
|
SetValue(value + 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TIconButton::Key(sf::Keyboard::Key key, bool released) {
|
|
if (released) return;
|
|
|
|
if (key == sf::Keyboard::Down) { // Arrow down/left
|
|
SetValue(value - 1);
|
|
} else if (key == sf::Keyboard::Up) { // Arrow up/right
|
|
SetValue(value + 1);
|
|
}
|
|
}
|
|
|
|
TIconButton* AddIconButton(int x, int y, const sf::Texture& texture, float size, int maximum, int value) {
|
|
locked_UD = true;
|
|
return static_cast<TIconButton*>(AddWidget(new TIconButton(x, y, texture, size, maximum, value)));
|
|
}
|
|
|
|
TArrow::TArrow(int x, int y, bool down_)
|
|
: TWidget(x, y, 32 * Winsys.scale / 0.8f, 16 * Winsys.scale / 0.8f)
|
|
, sprite(Tex.GetSFTexture(LB_ARROWS))
|
|
, down(down_) {
|
|
sprite.setPosition(x, y);
|
|
sprite.setScale(Winsys.scale / 0.8f, Winsys.scale / 0.8f);
|
|
|
|
SetTexture();
|
|
}
|
|
|
|
void TArrow::Focussed() {
|
|
SetTexture();
|
|
}
|
|
|
|
void TArrow::Activated() {
|
|
SetTexture();
|
|
}
|
|
|
|
void TArrow::SetTexture() {
|
|
static const float textl[6] = { 0.5f, 0.f, 0.5f, 0.5f, 0.f, 0.5f };
|
|
static const float texbr[6] = { 0.5f, 0.5f, 0.f, 0.75f, 0.75f, 0.25f };
|
|
|
|
int type = 0;
|
|
if (active)
|
|
type = 1;
|
|
if (focus)
|
|
type++;
|
|
if (down)
|
|
type += 3;
|
|
|
|
sf::Vector2u texSize = sprite.getTexture()->getSize();
|
|
sprite.setTextureRect(sf::IntRect(textl[type] * texSize.x, texbr[type] * texSize.y, texSize.x / 2, texSize.y / 4));
|
|
}
|
|
|
|
void TArrow::Draw() const {
|
|
Winsys.draw(sprite);
|
|
}
|
|
|
|
TArrow* AddArrow(int x, int y, bool down) {
|
|
return static_cast<TArrow*>(AddWidget(new TArrow(x, y, down)));
|
|
}
|
|
|
|
|
|
TUpDown::TUpDown(int x, int y, int min_, int max_, int value_, int distance, bool swapArrows_)
|
|
: TWidget(x, y, 32 * Winsys.scale / 0.8f, (32 + distance)*Winsys.scale / 0.8f)
|
|
, up(x, y + (16 + distance)*Winsys.scale / 0.8f, true)
|
|
, down(x, y, false)
|
|
, higher(swapArrows_ ? up : down)
|
|
, lower(swapArrows_ ? down : up)
|
|
, value(value_)
|
|
, minimum(min_)
|
|
, maximum(max_)
|
|
, swapArrows(swapArrows_) {
|
|
lower.SetActive(value < maximum);
|
|
higher.SetActive(value > minimum);
|
|
}
|
|
|
|
void TUpDown::Draw() const {
|
|
up.Draw();
|
|
down.Draw();
|
|
}
|
|
|
|
bool TUpDown::Click(int x, int y) {
|
|
if (active && visible && lower.Click(x, y)) {
|
|
value++;
|
|
higher.SetActive(true);
|
|
if (value == maximum)
|
|
lower.SetActive(false);
|
|
return true;
|
|
}
|
|
if (active && visible && higher.Click(x, y)) {
|
|
lower.SetActive(true);
|
|
value--;
|
|
if (value == minimum)
|
|
down.SetActive(false);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TUpDown::Key(sf::Keyboard::Key key, bool released) {
|
|
if (released) return;
|
|
|
|
if ((!swapArrows && key == sf::Keyboard::Up) || (swapArrows && key == sf::Keyboard::Down)) { // Arrow up
|
|
if (value > minimum) {
|
|
value--;
|
|
lower.SetActive(true);
|
|
if (value == minimum)
|
|
higher.SetActive(false);
|
|
}
|
|
} else if ((!swapArrows && key == sf::Keyboard::Down) || (swapArrows && key == sf::Keyboard::Up)) { // Arrow down
|
|
if (value < maximum) {
|
|
value++;
|
|
higher.SetActive(true);
|
|
if (value == maximum)
|
|
lower.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TUpDown::MouseMove(int x, int y) {
|
|
bool ofocus = focus;
|
|
focus = active && visible && Inside(x, y, mouseRect);
|
|
if (ofocus != focus)
|
|
Focussed();
|
|
up.MouseMove(x, y);
|
|
down.MouseMove(x, y);
|
|
}
|
|
|
|
void TUpDown::SetValue(int value_) {
|
|
value = clamp(minimum, value_, maximum);
|
|
lower.SetActive(value < maximum);
|
|
higher.SetActive(value > minimum);
|
|
}
|
|
void TUpDown::SetMinimum(int min_) {
|
|
minimum = min_;
|
|
value = clamp(minimum, value, maximum);
|
|
lower.SetActive(value < maximum);
|
|
higher.SetActive(value > minimum);
|
|
}
|
|
void TUpDown::SetMaximum(int max_) {
|
|
maximum = max_;
|
|
value = clamp(minimum, value, maximum);
|
|
lower.SetActive(value < maximum);
|
|
higher.SetActive(value > minimum);
|
|
}
|
|
|
|
TUpDown* AddUpDown(int x, int y, int minimum, int maximum, int value, int distance, bool swapArrows) {
|
|
locked_UD = true;
|
|
return static_cast<TUpDown*>(AddWidget(new TUpDown(x, y, minimum, maximum, value, distance, swapArrows)));
|
|
}
|
|
|
|
// ------------------ Elementary drawing ---------------------------------------------
|
|
|
|
void DrawFrameX(int x, int y, int w, int h, int line, const sf::Color& backcol, const sf::Color& framecol, float transp) {
|
|
x += line;
|
|
y += line;
|
|
w -= line * 2;
|
|
h -= line * 2;
|
|
sf::RectangleShape shape(sf::Vector2f(w, h));
|
|
shape.setPosition(x, y);
|
|
shape.setOutlineThickness(line);
|
|
shape.setFillColor(sf::Color(backcol.r, backcol.g, backcol.b, backcol.a * transp));
|
|
shape.setOutlineColor(sf::Color(framecol.r, framecol.g, framecol.b, framecol.a * transp));
|
|
Winsys.draw(shape);
|
|
}
|
|
|
|
void DrawBonusExt(int y, std::size_t numraces, std::size_t num) {
|
|
std::size_t maxtux = numraces * 3;
|
|
if (num > maxtux) return;
|
|
|
|
static const sf::Color col2(115, 166, 217);
|
|
|
|
int lleft[3];
|
|
|
|
int framewidth = (int)numraces * 40 + 8;
|
|
int totalwidth = framewidth * 3 + 8;
|
|
int xleft = (Winsys.resolution.width - totalwidth) / 2;
|
|
lleft[0] = xleft;
|
|
lleft[1] = xleft + framewidth + 4;
|
|
lleft[2] = xleft + framewidth + framewidth + 8;
|
|
|
|
DrawFrameX(lleft[0], y, framewidth, 40, 1, col2, colBlack, 1);
|
|
DrawFrameX(lleft[1], y, framewidth, 40, 1, col2, colBlack, 1);
|
|
DrawFrameX(lleft[2], y, framewidth, 40, 1, col2, colBlack, 1);
|
|
|
|
static sf::Sprite tuxbonus(Tex.GetSFTexture(TUXBONUS));
|
|
sf::Vector2u size = tuxbonus.getTexture()->getSize();
|
|
tuxbonus.setTextureRect(sf::IntRect(0, 0, size.x, size.y/2));
|
|
|
|
for (std::size_t i=0; i<maxtux; i++) {
|
|
std::size_t majr = (i/numraces);
|
|
std::size_t minr = i - majr * numraces;
|
|
if (majr > 2) majr = 2;
|
|
int x = lleft[majr] + (int)minr * 40 + 6;
|
|
|
|
if (i<num) {
|
|
tuxbonus.setPosition(x, y + 4);
|
|
Winsys.draw(tuxbonus);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawGUIFrame() {
|
|
static sf::Sprite bottom_left(Tex.GetSFTexture(BOTTOM_LEFT));
|
|
static sf::Sprite bottom_right(Tex.GetSFTexture(BOTTOM_RIGHT));
|
|
static sf::Sprite top_left(Tex.GetSFTexture(TOP_LEFT));
|
|
static sf::Sprite top_right(Tex.GetSFTexture(TOP_RIGHT));
|
|
|
|
bottom_left.setPosition(0, Winsys.resolution.height - bottom_left.getTexture()->getSize().y);
|
|
bottom_right.setPosition(Winsys.resolution.width - bottom_right.getTexture()->getSize().x, Winsys.resolution.height - bottom_right.getTexture()->getSize().y);
|
|
top_right.setPosition(Winsys.resolution.width - top_right.getTexture()->getSize().x, 0);
|
|
|
|
Winsys.draw(bottom_left);
|
|
Winsys.draw(bottom_right);
|
|
Winsys.draw(top_left);
|
|
Winsys.draw(top_right);
|
|
}
|
|
|
|
void DrawGUIBackground(float scale) {
|
|
DrawGUIFrame();
|
|
|
|
static sf::Sprite logo(Tex.GetSFTexture(T_TITLE));
|
|
scale *= 0.5f;
|
|
logo.setScale(scale, scale);
|
|
logo.setPosition((Winsys.resolution.width - logo.getTextureRect().width*scale)/2, 5);
|
|
Winsys.draw(logo);
|
|
}
|
|
|
|
void DrawCursor() {
|
|
static sf::Sprite s(Tex.GetSFTexture(MOUSECURSOR));
|
|
static bool init = false;
|
|
if (!init) {
|
|
s.setScale((double) Winsys.resolution.width / 1400, (double) Winsys.resolution.width / 1400);
|
|
init = true;
|
|
}
|
|
s.setPosition(cursor_pos.x, cursor_pos.y);
|
|
Winsys.draw(s);
|
|
}
|
|
|
|
|
|
// ------------------ Main GUI functions ---------------------------------------------
|
|
|
|
void DrawGUI() {
|
|
for (std::size_t i = 0; i < Widgets.size(); i++)
|
|
if (Widgets[i]->GetVisible())
|
|
Widgets[i]->Draw();
|
|
if (param.ice_cursor)
|
|
DrawCursor();
|
|
}
|
|
|
|
TWidget* ClickGUI(int x, int y) {
|
|
TWidget* clicked = nullptr;
|
|
for (std::size_t i = 0; i < Widgets.size(); i++) {
|
|
if (Widgets[i]->Click(x, y)) {
|
|
clicked = Widgets[i];
|
|
lock_focussed = focussed;
|
|
}
|
|
}
|
|
return clicked;
|
|
}
|
|
|
|
TWidget* MouseMoveGUI(int x, int y) {
|
|
if (x != 0 || y != 0) {
|
|
focussed = -1;
|
|
for (std::size_t i = 0; i < Widgets.size(); i++) {
|
|
Widgets[i]->MouseMove(cursor_pos.x, cursor_pos.y);
|
|
if (Widgets[i]->focussed())
|
|
focussed = (int)i;
|
|
}
|
|
}
|
|
if (focussed == -1) {
|
|
focussed = lock_focussed;
|
|
if (focussed != -1) {
|
|
Widgets[focussed]->focus = true;
|
|
Widgets[focussed]->Focussed();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return Widgets[focussed];
|
|
}
|
|
|
|
TWidget* KeyGUI(sf::Keyboard::Key key, bool released) {
|
|
if (!released) {
|
|
switch (key) {
|
|
case sf::Keyboard::Tab:
|
|
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift) || sf::Keyboard::isKeyPressed(sf::Keyboard::RShift))
|
|
DecreaseFocus();
|
|
else
|
|
IncreaseFocus();
|
|
break;
|
|
case sf::Keyboard::Up:
|
|
if (!locked_UD)
|
|
DecreaseFocus();
|
|
break;
|
|
case sf::Keyboard::Left:
|
|
if (!locked_LR)
|
|
DecreaseFocus();
|
|
break;
|
|
case sf::Keyboard::Down:
|
|
if (!locked_UD)
|
|
IncreaseFocus();
|
|
break;
|
|
case sf::Keyboard::Right:
|
|
if (!locked_LR)
|
|
IncreaseFocus();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (focussed == -1)
|
|
return 0;
|
|
Widgets[focussed]->Key(key, released);
|
|
return Widgets[focussed];
|
|
}
|
|
|
|
TWidget* TextEnterGUI(char text) {
|
|
if (focussed == -1)
|
|
return 0;
|
|
Widgets[focussed]->TextEnter(text);
|
|
return Widgets[focussed];
|
|
}
|
|
|
|
void SetFocus(TWidget* widget) {
|
|
if (!widget)
|
|
focussed = -1;
|
|
else
|
|
for (std::size_t i = 0; i < Widgets.size(); i++) {
|
|
if (Widgets[i] == widget) {
|
|
Widgets[i]->focus = true;
|
|
Widgets[i]->Focussed();
|
|
focussed = (int)i;
|
|
break;
|
|
} else if (Widgets[i]->focus) {
|
|
Widgets[i]->focus = false;
|
|
Widgets[i]->Focussed();
|
|
}
|
|
}
|
|
}
|
|
|
|
void IncreaseFocus() {
|
|
if (focussed >= 0) {
|
|
Widgets[focussed]->focus = false;
|
|
Widgets[focussed]->Focussed();
|
|
}
|
|
|
|
focussed++;
|
|
if (focussed >= (int)Widgets.size())
|
|
focussed = 0;
|
|
int end = focussed;
|
|
// Select only active widgets
|
|
do {
|
|
if (Widgets[focussed]->GetActive() && Widgets[focussed]->GetInteractive())
|
|
break;
|
|
|
|
focussed++;
|
|
if (focussed >= (int)Widgets.size())
|
|
focussed = 0;
|
|
} while (end != focussed);
|
|
|
|
if (focussed >= 0) {
|
|
Widgets[focussed]->focus = true;
|
|
Widgets[focussed]->Focussed();
|
|
}
|
|
lock_focussed = focussed;
|
|
}
|
|
void DecreaseFocus() {
|
|
if (focussed >= 0) {
|
|
Widgets[focussed]->focus = false;
|
|
Widgets[focussed]->Focussed();
|
|
}
|
|
|
|
if (focussed > 0)
|
|
focussed--;
|
|
else
|
|
focussed = (int)Widgets.size()-1;
|
|
int end = focussed;
|
|
// Select only active widgets
|
|
do {
|
|
if (Widgets[focussed]->GetActive() && Widgets[focussed]->GetInteractive())
|
|
break;
|
|
|
|
if (focussed > 0)
|
|
focussed--;
|
|
else
|
|
focussed = (int)Widgets.size()-1;
|
|
} while (end != focussed);
|
|
|
|
if (focussed >= 0) {
|
|
Widgets[focussed]->focus = true;
|
|
Widgets[focussed]->Focussed();
|
|
}
|
|
lock_focussed = focussed;
|
|
}
|
|
|
|
void ResetGUI() {
|
|
for (std::size_t i = 0; i < Widgets.size(); i++)
|
|
delete Widgets[i];
|
|
Widgets.clear();
|
|
focussed = 0;
|
|
lock_focussed = -1;
|
|
locked_LR = locked_UD = false;
|
|
}
|
|
|
|
// ---------------------------------------------------------------
|
|
|
|
int AutoYPosN(int percent) {
|
|
return Winsys.resolution.height * percent / 100;
|
|
}
|
|
|
|
TArea AutoAreaN(int top_perc, int bott_perc, unsigned int w) {
|
|
TArea res;
|
|
res.top = AutoYPosN(top_perc);
|
|
res.bottom = AutoYPosN(bott_perc);
|
|
if (w > Winsys.resolution.width) w = Winsys.resolution.width;
|
|
res.left = (Winsys.resolution.width - w) / 2;
|
|
res.right = Winsys.resolution.width - res.left;
|
|
return res;
|
|
}
|