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_rect_list(0),
m_round_corners(WGT_AREA_ALL),
m_border_list(0),
m_scroll_pos_x(0), m_scroll_pos_y(0),
m_text_scale(1.0f)
{
@ -89,6 +90,12 @@ Widget::~Widget()
{
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))
{
//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
//color masking
if(!m_enable_rect)
@ -165,6 +176,26 @@ void Widget::update(const float DELTA)
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_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
//isn't based on pure logic, instead it's based on the perception of
//roundness and some visual testing.
//isn't based just on logic, since it went through visual testing to give
//the perception of roundness.
const int MIN_QUADS = 2;
const float QUAD_RADIUS_RAISE = 0.413f;
const int NUM_QUADS = MIN_QUADS + (int)(pow((float)radius, QUAD_RADIUS_RAISE));
const int NUM_QUADS = MIN_QUADS + radius;
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);
{
//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);
{
//These are used to center the widget; without centering, the
//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 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)
{
//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
//wasn't given, then the y position is computed as if it was
//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 )
{
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
{
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 )
{
vertex_yb = radius - circle_y;
outer_vertex[i][2] = radius - circle_y;
inner_vertex[i][2] = outer_vertex[i][2] + BORDER_LENGTH;
}
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);
glVertex2f(vertex_x - half_width, vertex_ya - half_height);
glTexCoord2f(inner_vertex[i][0] / (float)m_width, inner_vertex[i][1] / (float)m_height);
glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][1] - HALF_HEIGHT);
glTexCoord2f(vertex_x / m_width, vertex_yb / m_height);
glVertex2f(vertex_x - half_width, vertex_yb - half_height);
glTexCoord2f(inner_vertex[i][0] / (float)m_width, inner_vertex[i][2] / (float)m_height);
glVertex2f(inner_vertex[i][0] - HALF_WIDTH, inner_vertex[i][2] - HALF_HEIGHT);
}
//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
//drawn from left to right instead of right to left
circle_x = radius * sin(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 )
{
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
{
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 )
{
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
{
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);
glVertex2f(vertex_x - half_width, vertex_ya - half_height);
glTexCoord2f(vertex_x / m_width, vertex_yb / m_height);
glVertex2f(vertex_x - half_width, vertex_yb - half_height);
glTexCoord2f(inner_vertex[i+1][0] / (float)m_width, inner_vertex[i+1][2] / (float)m_height);
glVertex2f(inner_vertex[i+1][0] - HALF_WIDTH, inner_vertex[i+1][2] - HALF_HEIGHT);
}
}
glEnd();
}
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;
}

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_BLUE [4];
extern const GLfloat WGT_TRANSPARENT [4];
extern const GLfloat WGT_TRANSPARENT [4];
class Widget
@ -136,11 +136,16 @@ class Widget
/* Low level features. They are off by default. */
bool m_enable_rect;
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
//can change where it points to.
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;
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_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_texture = m_default_texture;
@ -746,6 +750,19 @@ void WidgetManager::setInitialRectState
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
(
@ -821,6 +838,9 @@ void WidgetManager::restoreDefaultStates()
m_default_show_rect = false;
m_default_rect_round_corners = WGT_AREA_NONE;
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_texture = 0;
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)
{
@ -1346,7 +1429,7 @@ int WidgetManager::handlePointer(const int X, const int Y )
++position;
}
delete select_buffer;
delete[] select_buffer;
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;
}
delete select_buffer;
delete[] select_buffer;
return WGT_NONE;
}

View File

@ -96,6 +96,10 @@ class WidgetManager
bool m_default_rect_round_corners;
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;
int m_default_texture;
@ -177,9 +181,23 @@ public:
/* On/off widget switch features. They are all disabled/hidden initially. */
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 setInitialBorderState
(
const bool SHOW,
const int PERCENTAGE,
const GLfloat* const COLOR
);
void setInitialTextState
(
const bool SHOW,
@ -222,6 +240,11 @@ public:
void showWgtRect(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 showWgtTexture(const int TOKEN);
void hideWgtTexture(const int TOKEN);