Widgets can now use borders + 2 memory leaks fixed found with valgrind within the Widget Manager's selection.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1677 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
cosmosninja 2008-03-31 01:02:20 +00:00
parent 122b22a77e
commit 1ebcbf4b7c
4 changed files with 226 additions and 39 deletions

View File

@ -77,6 +77,7 @@ Widget::Widget
m_width(WIDTH_), m_height(HEIGHT_), m_width(WIDTH_), m_height(HEIGHT_),
m_rect_list(0), m_rect_list(0),
m_round_corners(WGT_AREA_ALL), m_round_corners(WGT_AREA_ALL),
m_border_list(0),
m_scroll_pos_x(0), m_scroll_pos_y(0), m_scroll_pos_x(0), m_scroll_pos_y(0),
m_text_scale(1.0f) m_text_scale(1.0f)
{ {
@ -89,6 +90,12 @@ Widget::~Widget()
{ {
glDeleteLists(m_rect_list, 1); glDeleteLists(m_rect_list, 1);
} }
if(glIsList(m_border_list))
{
glDeleteLists(m_border_list, 1);
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -136,6 +143,10 @@ void Widget::update(const float DELTA)
if(glIsList(m_rect_list)) if(glIsList(m_rect_list))
{ {
//m_enable_rect == false doesn't disables this chunk of code because
//we still need to draw the rect into OpenGL's selection buffer even
//if it's not visible
//FIXME: maybe there is some sort of stacking method to disable/enable //FIXME: maybe there is some sort of stacking method to disable/enable
//color masking //color masking
if(!m_enable_rect) if(!m_enable_rect)
@ -165,6 +176,26 @@ void Widget::update(const float DELTA)
std::cerr << "(Did you created the rect?)\n"; std::cerr << "(Did you created the rect?)\n";
} }
if(glIsList(m_border_list))
{
if( m_enable_border )
{
glColor4fv(m_border_color);
//FIXME: I should probably revert the values to the defaults within the widget manager
//(if glPushAttrib() doesn't)
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glCallList(m_border_list);
}
}
else
{
std::cerr << "Warning: widget tried to draw null border list.\n";
std::cerr << "(Did you created the border?)\n";
}
if( m_enable_track ) if( m_enable_track )
{ {
if( m_track_num > (int)(track_manager->getTrackCount()) - 1) if( m_track_num > (int)(track_manager->getTrackCount()) - 1)
@ -553,31 +584,32 @@ bool Widget::createRect(int radius)
} }
//Calculate the number of quads each side should have. The algorithm //Calculate the number of quads each side should have. The algorithm
//isn't based on pure logic, instead it's based on the perception of //isn't based just on logic, since it went through visual testing to give
//roundness and some visual testing. //the perception of roundness.
const int MIN_QUADS = 2; const int MIN_QUADS = 2;
const float QUAD_RADIUS_RAISE = 0.413f; const int NUM_QUADS = MIN_QUADS + radius;
const int NUM_QUADS = MIN_QUADS + (int)(pow((float)radius, QUAD_RADIUS_RAISE));
int i; int i;
const int SMALLER_SIDE_LENGTH = m_height < m_width ? m_height / 2 : m_width / 2;
const float BORDER_LENGTH = SMALLER_SIDE_LENGTH * m_border_percentage;
float inner_vertex [(NUM_QUADS + 1) * 2][3];
float outer_vertex [(NUM_QUADS + 1) * 2][3];
const float HALF_WIDTH = m_width * 0.5f;
const float HALF_HEIGHT = m_height * 0.5f;
glNewList(m_rect_list, GL_COMPILE); glNewList(m_rect_list, GL_COMPILE);
{ {
//To create a rounded rectangle, we generate lines that are
//progressively bigger, which are given as vertex points for each
//quad.
glBegin(GL_QUAD_STRIP); glBegin(GL_QUAD_STRIP);
{ {
//These are used to center the widget; without centering, the //These are used to center the widget; without centering, the
//widget's 0,0 coordinates are at the lower left corner. //widget's 0,0 coordinates are at the lower left corner.
float half_width = m_width * 0.5f;
float half_height = m_height * 0.5f;
float angle; float angle;
float circle_x, circle_y; float circle_x, circle_y;
float vertex_x, vertex_ya, vertex_yb;
//Draw the left side of a rectangle. //Draw the left side of the inside
for (i = 0; i <= NUM_QUADS; ++i) for (i = 0; i <= NUM_QUADS; ++i)
{ {
//To find the position in the X and Y axis of each point of //To find the position in the X and Y axis of each point of
@ -604,76 +636,120 @@ bool Widget::createRect(int radius)
//position for the circle is dependant on rect; if a corner //position for the circle is dependant on rect; if a corner
//wasn't given, then the y position is computed as if it was //wasn't given, then the y position is computed as if it was
//for a rectangle without rounder corners. //for a rectangle without rounder corners.
vertex_x = radius - circle_x; outer_vertex[i][0] = radius - circle_x;
inner_vertex[i][0] = outer_vertex[i][0] + BORDER_LENGTH;
if( m_round_corners & WGT_AREA_NW ) if( m_round_corners & WGT_AREA_NW )
{ {
vertex_ya = m_height + circle_y - radius; outer_vertex[i][1] = m_height + circle_y - radius;
inner_vertex[i][1] = outer_vertex[i][1] - BORDER_LENGTH;
} }
else else
{ {
vertex_ya = (float)m_height; outer_vertex[i][1] = m_height;
inner_vertex[i][1] = outer_vertex[i][1] - BORDER_LENGTH;
} }
if( m_round_corners & WGT_AREA_SW ) if( m_round_corners & WGT_AREA_SW )
{ {
vertex_yb = radius - circle_y; outer_vertex[i][2] = radius - circle_y;
inner_vertex[i][2] = outer_vertex[i][2] + BORDER_LENGTH;
} }
else else
{ {
vertex_yb = 0; outer_vertex[i][2] = 0;
inner_vertex[i][2] = outer_vertex[i][2] + BORDER_LENGTH;
} }
glTexCoord2f(vertex_x / m_width, vertex_ya / m_height); glTexCoord2f(inner_vertex[i][0] / (float)m_width, inner_vertex[i][1] / (float)m_height);
glVertex2f(vertex_x - half_width, vertex_ya - half_height); glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][1] - HALF_HEIGHT);
glTexCoord2f(vertex_x / m_width, vertex_yb / m_height); glTexCoord2f(inner_vertex[i][0] / (float)m_width, inner_vertex[i][2] / (float)m_height);
glVertex2f(vertex_x - half_width, vertex_yb - half_height); glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][2] - HALF_HEIGHT);
} }
//Draw the right side of a rectangle //Draw the right side of a rectangle
for (i = 0; i <= NUM_QUADS; ++i) for (i = NUM_QUADS; i < NUM_QUADS * 2 + 1; ++i)
{ {
angle = 0.5f * M_PI * (float) i / (float) NUM_QUADS; angle = 0.5f * M_PI * (float) (i - NUM_QUADS) / (float) NUM_QUADS;
//By inverting the use of sin and cos we get corners that are //By inverting the use of sin and cos we get corners that are
//drawn from left to right instead of right to left //drawn from left to right instead of right to left
circle_x = radius * sin(angle); circle_x = radius * sin(angle);
circle_y = radius * cos(angle); circle_y = radius * cos(angle);
vertex_x = m_width - radius + circle_x; outer_vertex[i+1][0] = m_width - radius + circle_x;
inner_vertex[i+1][0] = outer_vertex[i+1][0] - BORDER_LENGTH;
if( m_round_corners & WGT_AREA_NE ) if( m_round_corners & WGT_AREA_NE )
{ {
vertex_ya = m_height + circle_y - radius; outer_vertex[i+1][1] = m_height - radius + circle_y;
inner_vertex[i+1][1] = outer_vertex[i+1][1] - BORDER_LENGTH;
} }
else else
{ {
vertex_ya = (float)m_height; outer_vertex[i+1][1] = m_height;
inner_vertex[i+1][1] = outer_vertex[i+1][1] - BORDER_LENGTH;
} }
if( m_round_corners & WGT_AREA_SE ) if( m_round_corners & WGT_AREA_SE )
{ {
vertex_yb = radius - circle_y; outer_vertex[i+1][2] = radius - circle_y;
inner_vertex[i+1][2] = outer_vertex[i+1][2] + BORDER_LENGTH;
} }
else else
{ {
vertex_yb = 0; outer_vertex[i+1][2] = 0;
inner_vertex[i+1][2] = outer_vertex[i+1][2] + BORDER_LENGTH;
} }
glTexCoord2f(inner_vertex[i+1][0] / (float)m_width, inner_vertex[i+1][1] / (float)m_height);
glVertex2f(inner_vertex[i+1][0] - HALF_WIDTH, inner_vertex[i+1][1] - HALF_HEIGHT);
glTexCoord2f(vertex_x / m_width, vertex_ya / m_height); glTexCoord2f(inner_vertex[i+1][0] / (float)m_width, inner_vertex[i+1][2] / (float)m_height);
glVertex2f(vertex_x - half_width, vertex_ya - half_height); glVertex2f(inner_vertex[i+1][0] - HALF_WIDTH, inner_vertex[i+1][2] - HALF_HEIGHT);
glTexCoord2f(vertex_x / m_width, vertex_yb / m_height);
glVertex2f(vertex_x - half_width, vertex_yb - half_height);
} }
} }
glEnd(); glEnd();
} }
glEndList(); glEndList();
if(!glIsList(m_border_list))
{
m_border_list = glGenLists(1);
if(m_border_list == 0)
{
std::cerr << "Error: could not create a widget's border list.\n";
return false;
}
}
glNewList(m_border_list, GL_COMPILE);
{
glBegin(GL_QUAD_STRIP);
{
for (i = NUM_QUADS * 2 + 1; i >= 0 ; --i)
{
glVertex2f(outer_vertex[i][0] - HALF_WIDTH, outer_vertex[i][1] - HALF_HEIGHT);
glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][1] - HALF_HEIGHT);
}
for (i = 0; i <= NUM_QUADS * 2 + 1; ++i)
{
glVertex2f(outer_vertex[i][0] - HALF_WIDTH, outer_vertex[i][2] - HALF_HEIGHT);
glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][2] - HALF_HEIGHT);
}
//Close the border
glVertex2f(outer_vertex[NUM_QUADS * 2 + 1][0] - HALF_WIDTH, outer_vertex[NUM_QUADS * 2 + 1][1] - HALF_HEIGHT);
glVertex2f(inner_vertex[NUM_QUADS * 2 + 1][0] - HALF_WIDTH, inner_vertex[NUM_QUADS * 2 + 1][1] - HALF_HEIGHT);
}
glEnd();
}
glEndList();
return true; return true;
} }

View File

@ -119,7 +119,7 @@ extern const GLfloat WGT_LIGHT_TRANS_RED [4];
extern const GLfloat WGT_LIGHT_TRANS_GREEN [4]; extern const GLfloat WGT_LIGHT_TRANS_GREEN [4];
extern const GLfloat WGT_LIGHT_TRANS_BLUE [4]; extern const GLfloat WGT_LIGHT_TRANS_BLUE [4];
extern const GLfloat WGT_TRANSPARENT [4]; extern const GLfloat WGT_TRANSPARENT [4];
class Widget class Widget
@ -136,11 +136,16 @@ class Widget
/* Low level features. They are off by default. */ /* Low level features. They are off by default. */
bool m_enable_rect; bool m_enable_rect;
GLuint m_rect_list; //A display list number that draws the rectangle with GLuint m_rect_list; //A display list number that draws the rectangle with
//possibly rounded corners. //possibly rounded corners.
const GLfloat *m_rect_color; //This const cannot change the value it points to, but it const GLfloat *m_rect_color; //This const cannot change the value it points to, but it
//can change where it points to. //can change where it points to.
WidgetArea m_round_corners; WidgetArea m_round_corners;
bool m_enable_border;
GLuint m_border_list; //Display list for the border
float m_border_percentage;
const GLfloat *m_border_color;
bool m_enable_texture; bool m_enable_texture;
GLuint m_texture; GLuint m_texture;

View File

@ -82,6 +82,10 @@ bool WidgetManager::addWgt
new_id.widget->m_enable_rect = m_default_show_rect; new_id.widget->m_enable_rect = m_default_show_rect;
new_id.widget->m_rect_color = m_default_rect_color; new_id.widget->m_rect_color = m_default_rect_color;
new_id.widget->m_enable_border = m_default_show_border;
new_id.widget->m_border_percentage = m_default_border_percentage;
new_id.widget->m_border_color = m_default_border_color;
new_id.widget->m_enable_texture = m_default_show_texture; new_id.widget->m_enable_texture = m_default_show_texture;
new_id.widget->m_texture = m_default_texture; new_id.widget->m_texture = m_default_texture;
@ -746,6 +750,19 @@ void WidgetManager::setInitialRectState
m_default_rect_color = COLOR; m_default_rect_color = COLOR;
} }
//-----------------------------------------------------------------------------
void WidgetManager::setInitialBorderState
(
const bool SHOW,
const int PERCENTAGE,
const GLfloat* const COLOR
)
{
m_default_show_border = SHOW;
m_default_border_percentage = PERCENTAGE * 0.01;
m_default_border_color = COLOR;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void WidgetManager::setInitialTextureState void WidgetManager::setInitialTextureState
( (
@ -821,6 +838,9 @@ void WidgetManager::restoreDefaultStates()
m_default_show_rect = false; m_default_show_rect = false;
m_default_rect_round_corners = WGT_AREA_NONE; m_default_rect_round_corners = WGT_AREA_NONE;
m_default_rect_color = WGT_TRANS_BLACK; m_default_rect_color = WGT_TRANS_BLACK;
m_default_show_border = false;
m_default_border_percentage = 0.0;
m_default_border_color = WGT_TRANS_WHITE;
m_default_show_texture = false; m_default_show_texture = false;
m_default_texture = 0; m_default_texture = 0;
m_default_show_text = false; m_default_show_text = false;
@ -910,6 +930,69 @@ void WidgetManager::hideWgtRect(const int TOKEN)
} }
} }
//-----------------------------------------------------------------------------
void WidgetManager::setWgtBorderColor(const int TOKEN, const GLfloat* const COLOR)
{
const int ID = findId(TOKEN);
if( ID != WGT_NONE ) m_widgets[ID].widget->m_border_color = COLOR;
else
{
std::cerr << "WARNING: tried to change the border color of an " <<
"unnamed widget with token " << TOKEN << '\n';
}
}
//-----------------------------------------------------------------------------
void WidgetManager::setWgtBorderPercentage(const int TOKEN, const int PERCENTAGE)
{
if( PERCENTAGE > 100 )
{
std::cerr << "WARNING: tried to set the border's percentage of " <<
"widget with token " << TOKEN << " to something bigger than " <<
"100% \n";
return;
}
else if( PERCENTAGE < 1 )
{
std::cerr << "WARNING: tried to set the border's percentage of " <<
"widget with token " << TOKEN << " to something smaller than " <<
"1% \n";
return;
}
const int ID = findId(TOKEN);
if( ID != WGT_NONE ) m_widgets[ID].widget->m_border_percentage = PERCENTAGE * 0.01;
else
{
std::cerr << "WARNING: tried to change the rect color of an " <<
"unnamed widget with token " << TOKEN << '\n';
}
}
//-----------------------------------------------------------------------------
void WidgetManager::showWgtBorder(const int TOKEN)
{
const int ID = findId(TOKEN);
if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_border = true;
else
{
std::cerr << "WARNING: tried to show the border of an unnamed widget "
<< "with token " << TOKEN << '\n';
}
}
//-----------------------------------------------------------------------------
void WidgetManager::hideWgtBorder(const int TOKEN)
{
const int ID = findId(TOKEN);
if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_border = false;
else
{
std::cerr << "WARNING: tried to hide the border of an unnamed widget "
<< "with token " << TOKEN << '\n';
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void WidgetManager::setWgtTexture(const int TOKEN, const int TEXTURE) void WidgetManager::setWgtTexture(const int TOKEN, const int TEXTURE)
{ {
@ -1346,7 +1429,7 @@ int WidgetManager::handlePointer(const int X, const int Y )
++position; ++position;
} }
delete select_buffer; delete[] select_buffer;
if( m_widgets[nearest_id].token == m_selected_wgt_token ) if( m_widgets[nearest_id].token == m_selected_wgt_token )
{ {
@ -1357,7 +1440,7 @@ int WidgetManager::handlePointer(const int X, const int Y )
return m_selected_wgt_token; return m_selected_wgt_token;
} }
delete select_buffer; delete[] select_buffer;
return WGT_NONE; return WGT_NONE;
} }

View File

@ -96,6 +96,10 @@ class WidgetManager
bool m_default_rect_round_corners; bool m_default_rect_round_corners;
const GLfloat *m_default_rect_color; const GLfloat *m_default_rect_color;
bool m_default_show_border;
float m_default_border_percentage;
const GLfloat *m_default_border_color;
bool m_default_show_texture; bool m_default_show_texture;
int m_default_texture; int m_default_texture;
@ -177,9 +181,23 @@ public:
/* On/off widget switch features. They are all disabled/hidden initially. */ /* On/off widget switch features. They are all disabled/hidden initially. */
void setInitialActivationState( const bool ACTIVE); void setInitialActivationState( const bool ACTIVE);
void setInitialRectState(const bool SHOW, const WidgetArea ROUND_CORNERS, const GLfloat* const COLOR );
void setInitialRectState
(
const bool SHOW,
const WidgetArea ROUND_CORNERS,
const GLfloat* const COLOR
);
void setInitialTextureState(const bool SHOW, const int TEXTURE ); void setInitialTextureState(const bool SHOW, const int TEXTURE );
void setInitialBorderState
(
const bool SHOW,
const int PERCENTAGE,
const GLfloat* const COLOR
);
void setInitialTextState void setInitialTextState
( (
const bool SHOW, const bool SHOW,
@ -222,6 +240,11 @@ public:
void showWgtRect(const int TOKEN); void showWgtRect(const int TOKEN);
void hideWgtRect(const int TOKEN); void hideWgtRect(const int TOKEN);
void setWgtBorderColor(const int TOKEN, const GLfloat* const COLOR);
void setWgtBorderPercentage(const int TOKEN, const int PERCENTAGE);
void showWgtBorder(const int TOKEN);
void hideWgtBorder(const int TOKEN);
void setWgtTexture(const int TOKEN, const int TEXTURE); void setWgtTexture(const int TOKEN, const int TEXTURE);
void showWgtTexture(const int TOKEN); void showWgtTexture(const int TOKEN);
void hideWgtTexture(const int TOKEN); void hideWgtTexture(const int TOKEN);