I wanted to make my own GUI for learning purposes and for a project i'm doing. I am looking for advice on what I should be doing differently (both in terms of how I used SFML and generic programming practices). I also would like to know the best way to make these buttons interact (in general) with other objects in the world. Here is my code for a Button class that I have made, I didn't write all the functions just to save reading and space. On top of this Button class, I might make a Menu class, to hold and position buttons.
P.S. I looked a lot of my questions up, but it really just came down to a matter of whether I understood it or not, but I can't be certain I did. This code works, (except for the obvious English substitutions) but it's probably not the best method.
class Button
{
public:
//Construct and Destruct
Button();
Button(string text);
~Button();
//Set
void setText(string text);//text displayed
void setTexture(string textureFile);//texture used for sprite
void setFont(string fontFile);//font type
void setPosition(sf::Vector2f position);//position of button by center
void setColor(sf::Color color);//color modifyer for sprite
void setOverHang(int overHang);//overHang is how much larger the sprite is than the text
void setCharSize(int charSize);
//Get
const string getText();
const sf::Texture getTexture();
const sf::Font getFont();//returns what type of font is being used
const sf::Vector2f getPosition();//returns center of button
const sf::Vector2i getDimensions();//returns size of the sprite, not text size!
const sf::Color getColor();
const int getOverHang();
const int getCharSize();
const sf::Sprite getSprite();
//Take Action
void leftClicked();//these will do something
void rightClicked();
void middleClicked();
void mouseOver();
void draw(sf::RenderWindow& renderWindow);
private:
sf::Texture* myTexture;//I need to keep textures until the object is destroyed right?
sf::Font* myFont;//do i need to keep fonts though?
sf::Text* myText;
sf::Sprite* mySprite;
};
///In Button.cpp
Button::Button()
{
myFont = new sf::Font();
myText = new sf::Text();
myTexture = new sf::Texture();
mySprite = new sf::Sprite();
}
Button::Button(string text)
{
myFont = new sf::Font();
myText = new sf::Text();
myTexture = new sf::Texture();
mySprite = new sf::Sprite();
///inputs
myText->setString(text);
///defaults
int posX = 100;
int posY = 100;
int charSize = 20;
int overHang = 2;
myFont->loadFromFile("Georgia.ttf");
myTexture->loadFromFile("button_grey.png");
myText->setFont(*myFont);
myText->setCharacterSize(charSize);
myText->setStyle(sf::Text::Bold);
myText->setColor(sf::Color::Black);
sf::FloatRect textRect = myText->getGlobalBounds();
myText->setOrigin(textRect.left + (textRect.width/2), textRect.top + (textRect.height/2));
myText->setPosition(posX, posY);
sf::IntRect spriteRect(0, 0, textRect.width+2*overHang, textRect.height+2*overHang);
mySprite->setTexture(*myTexture);
mySprite->setTextureRect(spriteRect);
mySprite->setOrigin(spriteRect.width/2, spriteRect.height/2);
mySprite->setPosition(posX, posY);
//mySprite->setColor(sf::Color(255, 255, 255, 255));
mySprite->setPosition(myText->getPosition());
}
Button::~Button()
{
delete mySprite;
delete myTexture;
delete myText;
delete myFont;
}
void Button::setPosition(sf::Vector2f position)
{
mySprite->setPosition(position);
myText->setPosition(position);
}
void Button::setTexture(string textureFile)
{
myTexture->loadFromFile(textureFile);
}
void Button::setFont(string fontFile)
{
myFont->loadFromFile(fontFile);
}
void Button::leftClicked()
{
///We got left clicked on! do something
}
//same for mouse over, and all other clicked actions
void Button::draw(sf::RenderWindow& renderWindow)
{
renderWindow.draw(*mySprite);
renderWindow.draw(*myText);
}
///EXAMPLE CODE
//similar for Mouse Moved ect.
//If i had a menu class, rather than checking against all buttons on screen, i could check whether the
//mouse was over a given menu, one at a time. If yes, go into that menu, do that button, and exit out
//of the loop. Thus not having to check every button on screen.
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.mouseButton.button == sf::Mouse::Left)
for(all buttons in the list)
{
if (button.getSprite()->getGlobalBounds().contains(window.mapPixelToCoords(mouseCoordinates)))
button.leftClicked();
}
}
for(all buttons in the list)
button.draw(window);