Skip to content

Commit

Permalink
improved buttons and menus
Browse files Browse the repository at this point in the history
Changes:
-added warning menu
-improved click detection
-fixed button overlap
-improved menu formatting
-menus can have subtitles
  • Loading branch information
confuzedskull committed Oct 17, 2014
1 parent 5e1b8b8 commit dc9feca
Show file tree
Hide file tree
Showing 17 changed files with 392 additions and 160 deletions.
38 changes: 17 additions & 21 deletions include/button.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,26 @@
#ifndef BUTTON_H
#define BUTTON_H
#include "clickable_object.h"
#include "text_object.h"

//A button displays text and executes a function when clicked
class button : public clickable_object
{
protected:
char* label;
void* font;
float font_size;//the height of the font in pt (not pixels)
public:
bool border;
color border_color;
float label_margin;//space between text and button border
float spacing;//space between each line
bool hovered_over();
bool left_clicked();
bool performed_action;
void (*action)();//a function pointer which will be called when clicked
void format();//adjusts the size of the button to fit the text
void set_label(char* l);
void set_font(void* f);
void mouse_function();
void render();
void update();
button();
button(float x, float y, char* l, void (*a)(void));
protected:
text_object label;
public:
bool border;//whether or not a border should be shown
color border_color;//the color of the border
int margin;//space between text and button border
bool performed_action;//whether or not the button action executed
void (*action)();//a function pointer which will be called when clicked
void format();//adjusts the size of the button to fit the text
void set_label(char* l);
void mouse_function();
void render();
void update();
button();
button(float x, float y, char* l, void (*a)(void));
};

#endif // BUTTON_H
1 change: 1 addition & 0 deletions include/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ class cursor
static int objects_selected();
static void calc_boundaries();
static void selection_box();
static void reset();
};
#endif // CURSOR_H
3 changes: 2 additions & 1 deletion include/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ namespace game
void play();//open game screen
void pause();//open pause screen
void resume();//open game screen
void go_home();//open main menu
void return_warning();//warn user before returning to main menu
void return_menu();//open main menu
void quit();//close the program
};
#endif // GAME_H
15 changes: 6 additions & 9 deletions include/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,22 @@
#ifndef MENU_H
#define MENU_H
#include "button.h"
#include "text_object.h"
#include <vector>

class menu: public object
{
protected:
char* title;
void* font;
int font_width;
int font_height;
text_object title;
text_object subtitle;
public:
std::vector<button*> items;
int layout;
int spacing;
int spacing;//space between buttons
int margin;
void open();
void close();
void format();
void set_title(char* t);
void set_font(void* f);
void set_subtitle(char* s);
void format();
void render();
void update();
menu();
Expand Down
43 changes: 43 additions & 0 deletions include/text_object.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* This file is a part of 2DWorld - The Generic 2D Game Engine
Copyright (C) 2014 James Nakano
2DWorld 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 3 of the License, or
(at your option) any later version.
2DWorld 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.
You should have received a copy of the GNU General Public License
along with the rest of 2DWorld. If not, see <http://www.gnu.org/licenses/>.*/

#ifndef TEXT_OBJECT_H
#define TEXT_OBJECT_H
#include "object.h"

//A text object stores a string which can be formatted and displayed on screen
class text_object: public object
{
protected:
char* text;
void* font;
int font_size;
int font_width;
int font_height;
int lines;
int longest_line;//the length of the longest line (excluding newline character)
public:
int spacing;//the space between each line
float get_width();//overrides object::get_width()
float get_height();//overrides object::get_height()
void set_text(char* t);
void set_font(char* style, int size);
void calc_lines();//finds the number of lines and the length of the longest line
void render();//prints the text to the screen
text_object();
};

#endif // TEXT_OBJECT_H
73 changes: 23 additions & 50 deletions src/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,48 +34,19 @@
#include <math.h>
#include <string.h>

bool button::hovered_over()
{
if(!cursor::left_click &&
isless(cursor::passive.x,xmax) && isgreater(cursor::passive.x,xmin) &&
isless(cursor::passive.y,ymax) && isgreater(cursor::passive.y,ymin))
return true;
else
return false;
}

bool button::left_clicked()
{
if(cursor::left_click &&
isless(cursor::left_down.x,xmax) && isgreater(cursor::left_down.x,xmin) &&
isless(cursor::left_down.y,ymax) && isgreater(cursor::left_down.y,ymin))
return true;
else
return false;
}

void button::format()
{
width=(((float)strlen(label))*(font_size*0.6f))+(label_margin*2.0f);
height=font_size+(label_margin*2.0f);
width=label.get_width()+(margin*2);
height=label.get_height()+(margin*2);
calc_boundaries();
}

void button::set_label(char* l)
{
label=l;
label.set_text(l);
format();
}

void button::set_font(void* f)
{
font=f;
if(f==GLUT_BITMAP_HELVETICA_12)
font_size=12;
if(f==GLUT_BITMAP_HELVETICA_18)
font_size=18;
}

void button::mouse_function()
{
if(visible)
Expand All @@ -84,12 +55,15 @@ void button::mouse_function()
primary_color.brighten();
if(!hovered_over())
primary_color.undo();
if(left_clicked() && !performed_action)
if(left_clicked())
{
action();
performed_action=true;
if(!performed_action)
{
action();
performed_action=true;
}
}
if(!left_clicked())
else
performed_action=false;
}
}
Expand Down Expand Up @@ -120,7 +94,8 @@ void button::render()
glEnd();
}
//render button text
ui::glutPrint(xmin+label_margin,ymin+label_margin+spacing,font,label);
label.set_position(position.x-(label.get_width()/2),position.y-(label.get_height()/2));
label.render();
}

void button::update()
Expand All @@ -130,31 +105,29 @@ void button::update()

button::button()
{
label="click me";
type="button";
label_margin=6.0f;
font=GLUT_BITMAP_HELVETICA_12;
font_size=12.0f;
spacing=1.0f;
set_label("click me");
margin=5;
position.set(0.0f,0.0f);
format();
primary_color.set(0.75f,0.75f,0.75f);
primary_color.changed=false;
border=true;
border_color=BLACK;
performed_action=false;
std::clog<<"object#"<<number<<": "<<label<<'('<<type<<')'<<" created. "<<sizeof(*this)<<" bytes"<<std::endl;
std::clog<<"object#"<<number<<": "<<name<<'('<<type<<')'<<" created. "<<sizeof(*this)<<" bytes"<<std::endl;
}

button::button(float x, float y, char* l, void (*a)(void))
{
label="click me";
type="button";
label_margin=6.0f;
set_font(GLUT_BITMAP_HELVETICA_12);
spacing=1.0f;
set_label("click me");
margin=5;
position.set(x,y);
set_label(l);
primary_color.set(0.75f,0.75f,0.75f);
primary_color.changed=false;
action=a;
std::clog<<"object#"<<number<<": "<<label<<'('<<type<<')'<<" created. "<<sizeof(*this)<<" bytes"<<std::endl;
border=true;
border_color=BLACK;
performed_action=false;
std::clog<<"object#"<<number<<": "<<name<<'('<<type<<')'<<" created. "<<sizeof(*this)<<" bytes"<<std::endl;
}
16 changes: 11 additions & 5 deletions src/clickable_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,29 @@

bool clickable_object::hovered_over()
{
if(isless(distance(cursor::passive,position),radius))
if(!cursor::left_click &&
isless(cursor::passive.x,xmax) && isgreater(cursor::passive.x,xmin) &&
isless(cursor::passive.y,ymax) && isgreater(cursor::passive.y,ymin))
return true;
else
return false;
}

bool clickable_object::left_clicked()
{
if(cursor::left_click && isless(distance(cursor::left_down,position),radius))
if(cursor::left_click &&
isless(cursor::left_down.x,xmax) && isgreater(cursor::left_down.x,xmin) &&
isless(cursor::left_down.y,ymax) && isgreater(cursor::left_down.y,ymin))
return true;
else
return false;
}

bool clickable_object::right_clicked()
{
if(cursor::right_click && isless(distance(cursor::right_down,position),radius))
if(cursor::right_click &&
isless(cursor::right_down.x,xmax) && isgreater(cursor::right_down.x,xmin) &&
isless(cursor::right_down.y,ymax) && isgreater(cursor::right_down.y,ymin))
return true;
else
return false;
Expand All @@ -48,15 +54,15 @@ void clickable_object::mouse_function()
{
if(left_clicked())//clicked this object
{
if(!cursor::left_clicked_an_object && !selected)
if(!selected)
std::clog<<"object#"<<number<<": "<<name<<'('<<type<<')'<<" selected"<<std::endl;
cursor::left_clicked_object=this;
cursor::left_clicked_an_object = true;
cursor::selected_object=number;
selected = true;
}

if(cursor::left_click && cursor::selected_object !=number)//clicked another object
if(cursor::left_click && cursor::left_clicked_an_object && cursor::selected_object!=number)//clicked another object
{
cursor::highlighted_objects[number]=false;
selected = false;
Expand Down
42 changes: 29 additions & 13 deletions src/controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,44 @@ bool controls::toggle_overlay = false;
void controls::check_clicked()
{
//The only way to check if no objects are being clicked is by checking every object
bool left_clicked=true;
bool right_clicked=true;
for(std::map<int,rts_object*>::iterator a=game::rts_objects.begin(); a!=game::rts_objects.end(); ++a)
bool left_clicked=false;
while(!left_clicked)
{
if(left_clicked && a->second->left_clicked())
left_clicked=true;
else
left_clicked=false;

if(right_clicked && a->second->right_clicked())
right_clicked=true;
else
right_clicked=false;
for(std::map<int,rts_object*>::iterator a=game::rts_objects.begin(); a!=game::rts_objects.end(); ++a)
left_clicked=a->second->left_clicked();
for(std::map<int,draggable_object*>::iterator a=game::draggable_objects.begin(); a!=game::draggable_objects.end(); ++a)
left_clicked=a->second->left_clicked();
for(std::map<int,physics_object*>::iterator a=game::physics_objects.begin(); a!=game::physics_objects.end(); ++a)
left_clicked=a->second->left_clicked();
for(unsigned i=0;i<ui::buttons.size();i++)
left_clicked=ui::buttons[i]->left_clicked();
if(!left_clicked)//at this point, no objects have been left clicked so leave the loop
break;
}
cursor::left_clicked_an_object = left_clicked;

bool right_clicked=false;
while(!right_clicked)
{
for(std::map<int,rts_object*>::iterator a=game::rts_objects.begin(); a!=game::rts_objects.end(); ++a)
right_clicked=a->second->right_clicked();
for(std::map<int,draggable_object*>::iterator a=game::draggable_objects.begin(); a!=game::draggable_objects.end(); ++a)
right_clicked=a->second->right_clicked();
for(std::map<int,physics_object*>::iterator a=game::physics_objects.begin(); a!=game::physics_objects.end(); ++a)
right_clicked=a->second->right_clicked();
if(!right_clicked)//at this point, no objects have been right clicked so leave the loop
break;
}
cursor::right_clicked_an_object = right_clicked;

bool grabbed=true;
for(std::map<int,draggable_object*>::iterator a=game::draggable_objects.begin(); a!=game::draggable_objects.end(); ++a)
{
if(grabbed && a->second->grabbed())
if(a->second->grabbed())
{
grabbed=true;
break;
}
else
grabbed=false;
}
Expand Down
Loading

0 comments on commit dc9feca

Please sign in to comment.