switched to a simpler collision-detection algorithm to detect mouse clicks on GUI items
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2297 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
0e5106bfb9
commit
b1ffefe0a4
@ -1764,108 +1764,24 @@ int WidgetManager::handlePointer(const int X, const int Y )
|
||||
const int NUM_WGTS = (int)m_widgets.size();
|
||||
if( NUM_WGTS < 1 ) return WGT_NONE;
|
||||
|
||||
//OpenGL provides a mechanism to select objects; simply 'draw' named
|
||||
//objects, and for each non-culled visible object a 'hit' will be saved
|
||||
//into a selection buffer. Objects are named by using OpenGL's name
|
||||
//stack. The information in each hit is the number of names in the name
|
||||
//stack, two hard-to-explain depth values that aren't used in this
|
||||
//function, and the contents of the name stack at the time of the hit.
|
||||
|
||||
//This function loads 1 name into the stack (because if you pop an empty
|
||||
//stack you get an error), then uses glLoadName (which is a shortcut for
|
||||
//popping then pushing) to change the name. That means that each time a
|
||||
//hit is recorded, only the last drawn widget will be on the name stack.
|
||||
|
||||
const int HIT_SIZE = 4; //1 Gluint for the number of names, 2 depth
|
||||
//values, and 1 for the token of the widget.
|
||||
const int BUFFER_SIZE = HIT_SIZE * NUM_WGTS;
|
||||
|
||||
GLuint* select_buffer = new GLuint[BUFFER_SIZE];
|
||||
glSelectBuffer(BUFFER_SIZE, select_buffer);
|
||||
|
||||
glRenderMode(GL_SELECT);
|
||||
|
||||
//Set the viewport to draw only what's under the mouse
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT,viewport);
|
||||
gluPickMatrix(X, Y, 1,1,viewport);
|
||||
glOrtho(0.0, user_config->m_width, 0.0, user_config->m_height, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glInitNames();
|
||||
glPushName(WGT_NONE);
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
for( int i = 0; i < NUM_WGTS; ++i )
|
||||
{
|
||||
if(!(m_widgets[i].active)) continue;
|
||||
|
||||
glLoadName( i );
|
||||
const int offset = m_widgets[i].widget->m_radius/4;
|
||||
|
||||
glPushMatrix();
|
||||
m_widgets[i].widget->applyTransformations();
|
||||
//In case this ever becomes a performance bottleneck:
|
||||
//the m_rect_list includes texture coordinates, which are not
|
||||
//needed for selection.
|
||||
glCallList( m_widgets[i].widget->m_rect_list );
|
||||
glPopMatrix();
|
||||
}
|
||||
glFlush();
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glFlush();
|
||||
|
||||
GLuint* position = select_buffer;
|
||||
const GLint NUM_HITS = glRenderMode(GL_RENDER);
|
||||
|
||||
if( NUM_HITS > 0 )
|
||||
{
|
||||
float dist;
|
||||
float near_dist = 9999999.0f;
|
||||
int curr_wgt_id;
|
||||
int nearest_id = WGT_NONE;
|
||||
int wgt_x_center, wgt_y_center;
|
||||
for( int i = 0; i < NUM_HITS; ++i )
|
||||
if(X > m_widgets[i].widget->m_x+offset &&
|
||||
X < m_widgets[i].widget->m_x + m_widgets[i].widget->m_width-offset &&
|
||||
Y > m_widgets[i].widget->m_y+offset &&
|
||||
Y < m_widgets[i].widget->m_y + m_widgets[i].widget->m_height-offset)
|
||||
{
|
||||
position += 3;
|
||||
curr_wgt_id = *position;
|
||||
|
||||
wgt_x_center = m_widgets[curr_wgt_id].widget->m_x +
|
||||
(m_widgets[i].widget->m_width / 2);
|
||||
wgt_y_center = m_widgets[curr_wgt_id].widget->m_y +
|
||||
(m_widgets[i].widget->m_height / 2);
|
||||
|
||||
//Check if it's the closest one to the mouse
|
||||
dist = (float)( abs(X - wgt_x_center) + abs(Y - wgt_y_center));
|
||||
if(dist < near_dist )
|
||||
{
|
||||
near_dist = dist;
|
||||
nearest_id = curr_wgt_id;
|
||||
}
|
||||
|
||||
++position;
|
||||
}
|
||||
delete[] select_buffer;
|
||||
|
||||
if( m_widgets[nearest_id].token == m_selected_wgt_token )
|
||||
{
|
||||
return WGT_NONE;
|
||||
if(m_widgets[i].token == getSelectedWgt()) return WGT_NONE;
|
||||
setSelectedWgtToken( m_widgets[i].token );
|
||||
return m_selected_wgt_token;
|
||||
}
|
||||
|
||||
setSelectedWgtToken( m_widgets[nearest_id].token );
|
||||
return m_selected_wgt_token;
|
||||
}
|
||||
|
||||
delete[] select_buffer;
|
||||
return WGT_NONE;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user