Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added comments #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions guibutton.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@

using namespace std;

/*Create a struct we can use to place buttons, of type GUIElement of course
It has private variables for colors, default sizes/etc for the button itself
and then some functions to do things like see where it is, see if a point
is inside of it, and handle events.
*/
struct GUIButton : public GUIElement
{
wstring title;
wstring title;
Color textColor;
Color selectedTextColor;
Color buttonColor;
Expand All @@ -34,10 +39,14 @@ struct GUIButton : public GUIElement
selectedTextColor(selectedTextColor), buttonColor(buttonColor),
selectedButtonColor(selectedButtonColor), buttonPressEvent([]()
{
//Basically this function should be overwritten to actually function properly, so if this is called
//and runs through to here that's a problem -- throw an error
throw logic_error("button press event function called instead of overridden member");
})
{
}
//The following are some private variables the public functions use to determine things
//like is pointinside etc, pretty self-explanatory
private:
float getLeftToMiddleX() const
{
Expand All @@ -47,9 +56,16 @@ struct GUIButton : public GUIElement
{
return maxX - 0.5 * (maxY - minY);
}

//This is where things get interesting, here the button handles things like mouse events
//And determines if a point is inside it
public:
//This takes in an x,y coordinate and determines if it's inside the button.
//It uses the private functions and some relatively simple logic to do so.
virtual bool isPointInside(float x, float y) const override
{
//I believe this checks to see if it's in the element at all, which
//Is a larger area than this particular button
if(!GUIElement::isPointInside(x, y))
{
return false;
Expand All @@ -72,20 +88,26 @@ struct GUIButton : public GUIElement
x -= leftToMiddleX;
}

//Get the vertical midpoint of the button
float halfHeight = 0.5 * (maxY - minY);
y -= 0.5 * (minY + maxY);

//Basically if x^2 + y^2 < halfHeight^2 then it has to be inside the button
if(x * x + y * y < halfHeight * halfHeight)
{
return true;
}

return false;
}
//Check to see if this element can have the keyboard's focus
//I'm guessing this is for highlighting/etc and determining if
//You'll skip this element when using the keyboard/etc
virtual bool canHaveKeyboardFocus() const override
{
return true;
}
//Allows the button to change variables as needed when the mouse is released
virtual bool handleMouseUp(MouseUpEvent &event)
{
if(event.button == MouseButton_Left)
Expand All @@ -96,6 +118,7 @@ struct GUIButton : public GUIElement

return GUIElement::handleMouseUp(event);
}
//Run anything needed when the button is clicked, calls other button functions
virtual bool handleMouseDown(MouseDownEvent &event) override
{
if(event.button == MouseButton_Left)
Expand All @@ -109,11 +132,13 @@ struct GUIButton : public GUIElement

return GUIElement::handleMouseDown(event);
}
//If the button is sensitive to highlighting with mouse you can change things here
virtual bool handleMouseMoveOut(MouseEvent &event) override
{
isMousePressed = false;
isMousePressed = false; //Just to be safe really
return true;
}
//If the button has a key assigned then this handles that, send to the same function as a mouse click
virtual bool handleKeyDown(KeyDownEvent &event) override
{
if(!event.isRepetition && (event.key == KeyboardKey_Return || event.key == KeyboardKey_Space))
Expand All @@ -126,30 +151,37 @@ struct GUIButton : public GUIElement
return GUIElement::handleKeyDown(event);
}
protected:
//Simple function that allows children to see if the button is pressed
bool isPressed() const
{
return isMousePressed || (Display::timer() - lastDownTime < 0.1);
}
//a virtual void you can add stuff to in child classes, just redirects right now
virtual void handleButtonPress()
{
buttonPressEvent();
}
//Actually render the button, changes color if the button has focus
virtual Mesh render(float minZ, float maxZ, bool hasFocus) override
{
//Choose the colors of the button and text
Color buttonColor = this->buttonColor;
Color textColor = this->textColor;

//If we have the focus, then highlight the button
if(hasFocus)
{
buttonColor = this->selectedButtonColor;
textColor = this->selectedTextColor;
}

//Set some variables for displaying
bool pressed = isPressed();
float textWidth = Text::width(title);
float textHeight = Text::height(title);
float leftToMiddleX = getLeftToMiddleX();
float middleToRightX = getMiddleToRightX();
//Create the button by layering colored meshes on top of each other
Mesh diffuse = Generate::quadrilateral(TextureAtlas::ButtonLeftDiffuse.td(),
VectorF(minX, minY, -1), buttonColor,
VectorF(leftToMiddleX, minY, -1), buttonColor,
Expand Down Expand Up @@ -181,17 +213,19 @@ struct GUIButton : public GUIElement
VectorF(maxX, maxY, -1), Color(1),
VectorF(middleToRightX, maxY, -1), Color(1)));
Matrix buttonTransform = Matrix::identity();

//If the button is pressed, move it just a little bit to show that it's pressed
if(pressed)
{
float midX = (minX + maxX) * 0.5, midY = (minY + maxY) * 0.5;
buttonTransform = Matrix::translate(-midX, -midY,
0).concat(Matrix::rotateZ(M_PI)).concat(Matrix::translate(midX, midY, 0));
}

//Return the mesh of the transformed button/created
Mesh retval = (Mesh)transform(buttonTransform.concat(Matrix::scale(interpolate(2.0 / 3, minZ,
maxZ))), diffuse);

//If we have text, scaled it properly and change things depending on if it's pressed or not
if(textHeight > 0 && textWidth > 0)
{
float textScale = 0.5 * (maxY - minY) / textHeight;
Expand All @@ -208,16 +242,18 @@ struct GUIButton : public GUIElement
retval->add(transform(Matrix::scale(textScale).concat(Matrix::translate(xOffset, yOffset,
-1).concat(Matrix::scale(minZ))), Text::mesh(title, textColor)));
}

//Add the specular mesh to our return value
retval->add(transform(buttonTransform.concat(Matrix::scale(interpolate(1.0 / 3, minZ, maxZ))),
specular));
return retval;
}
//Reset the state of the button, where it hasn't been pressed yet
virtual void reset()
{
isMousePressed = false;
lastDownTime = -1;
}
//Some more basic private variables to use for the button state
private:
bool isMousePressed = false;
double lastDownTime = -1;
Expand Down