我有一个我希望能够移动的物体。我希望它只在我点击进入时移动,然后将鼠标拖到一个地方,然后在释放后,它开始向它移动。因此,如果我点击它,我可以在按住鼠标按钮的同时将鼠标移动到我想要的任何位置,但只有当我发布它才开始移动。
目前,只要我按住鼠标按钮并移动它,最好的我能做的就是让对象跟随(在btw后面几秒钟,而不是鼠标位置)。无论我从哪里开始点击,只要我点击并移动,只要我按住鼠标按钮,对象就会向它移动。任何其他尝试都会让对象保持静止/根本不动。
void mousemotion(int x, int yc){
globals.mouse_x = x;
globals.mouse_y = HEIGHT - yc;
}
和
int main(int argc, char** argv){
glutInit(&argc, argv);
....
//glutMouseFunc(processMouse);
glutMotionFunc(mousemotion);
是当前用于允许上述结果的唯一鼠标函数/回调。我尝试过添加glutMouseFunc
回调等内容,但更改state
参数会产生错误结果。 E.G:
//glutMouseFunc callback
void processMouse(int button, int state, int x, int yc){
if ( state == GLUT_UP){
globals.centre_x = globals.mouse_x;
globals.centre_y = globals.mouse_y;
}
GLUT_DOWN
不会改变主要行为,但是当对象处于运动状态时,我只需单击一次,对象就会捕捉到它要去的位置。 GLUT_UP
只是这样做,一旦我释放鼠标,对象将立即捕捉到它要去的位置。这些行为对于他们的表现方式是有意义的,但我不能操纵它以我想要的方式工作。我还做了一个函数来检查一个点是否在对象内,但我不知道它适用的位置
bool inside(int x, int y){
if(x >= globals.centre_x - 20
&& x <= globals.centre_x +20
&& y >= globals.centre_y - 20
&& y <= globals.centre_y+ 20){
return true;
}
else
return false;
}
据说它可以在鼠标功能中使用一次,使用x和y鼠标坐标作为参数。
我在网上看到的所有拖放示例都涉及立即拖动对象,即点击对象和对象在移动它时遵循精确的x,y鼠标坐标,但我想只在我让它时才这样做去掉鼠标会使物体开始移动。
任何帮助表示赞赏。让我知道我是否可以澄清任何事情。感谢
答案 0 :(得分:1)
我不使用GLUT但基于这些:
检测鼠标事件类型您需要执行以下操作:
//glutMouseFunc callback
int state0l=GLUT_UP; // last left mouse buttons state
int state0r=GLUT_UP; // last right mouse buttons state
void processMouse(int button, int state1, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
{
// decode and handle the mouse events by type
if ((state0l == GLUT_UP )&&(state1 == GLUT_DOWN)) // mouse down (click)
{
// here do your stuff
}
if ((state0l == GLUT_DOWN)&&(state1 == GLUT_DOWN)) // mouse move while clicked
{
// here do your stuff
}
if ((state0l == GLUT_DOWN)&&(state1 == GLUT_UP )) // mouse up (release)
{
// here do your stuff
}
if ((state0l == GLUT_UP )&&(state1 == GLUT_UP )) // mouse move without buttons
{
// here do your stuff
}
// store actual buttons state for next time
state0l = state1;
}
if (button == GLUT_RIGHT_BUTTON)
{
// decode and handle the mouse events by type
if ((state0r == GLUT_UP )&&(state1 == GLUT_DOWN)) // mouse down (click)
{
// here do your stuff
}
if ((state0r == GLUT_DOWN)&&(state1 == GLUT_DOWN)) // mouse move while clicked
{
// here do your stuff
}
if ((state0r == GLUT_DOWN)&&(state1 == GLUT_UP )) // mouse up (release)
{
// here do your stuff
}
if ((state0r == GLUT_UP )&&(state1 == GLUT_UP )) // mouse move without buttons
{
// here do your stuff
}
// store actual buttons state for next time
state0r = state1;
}
}
正如你所看到的,我只是检查按钮的最后和实际状态,以检测4种可能性+/-与我之前给你的链接相同:
当您检查方法时,我只有q0,q1
而不是state0,state1
:editor::mov,add_kruh,add_stvorec,...
它们都使用相同的技术(但只使用粗略的那些事件)。
答案 1 :(得分:0)
全部(右键单击以添加矩形):
#include <GL/glut.h>
// https://glm.g-truc.net/
#include <glm/glm.hpp>
#include <vector>
struct Rect
{
glm::vec2 pos;
glm::vec2 dim;
bool IsInside( glm::vec2 point ) const
{
const bool inX = pos.x < point.x && point.x < pos.x + dim.x;
const bool inY = pos.y < point.y && point.y < pos.y + dim.y;
return inX && inY;
}
};
// rect list & selection
std::vector< Rect > rects;
int selected = -1;
// animation state
int timeBeg = -1;
int timeEnd = -1;
glm::vec2 src;
glm::vec2 dst;
void mouse( int button, int state, int x, int y )
{
if( GLUT_RIGHT_BUTTON == button )
{
// add rect
if( GLUT_UP == state )
{
rects.push_back( Rect{ glm::vec2( x, y ), glm::vec2( 60, 60 ) } );
glutPostRedisplay();
}
return;
}
if( GLUT_LEFT_BUTTON == button && ( timeBeg < 0 || timeEnd < 0 ) )
{
// select rect
if( GLUT_DOWN == state )
{
for( size_t i = 0; i < rects.size(); ++i )
{
if( !rects[i].IsInside( glm::vec2( x, y ) ) )
continue;
selected = i;
glutPostRedisplay();
return;
}
}
// finish select
if( GLUT_UP == state && selected >= 0 )
{
timeBeg = glutGet( GLUT_ELAPSED_TIME );
timeEnd = timeBeg + 1000;
src = rects[ selected ].pos;
dst = glm::vec2( x, y );
}
return;
}
}
void timer( int value )
{
glutTimerFunc( 16, timer, 0 );
// don't repaint if we aren't animating
if( timeBeg < 0 || timeEnd < 0 || selected < 0 )
return;
const int timeCur = glutGet( GLUT_ELAPSED_TIME );
if( timeCur > timeEnd )
{
// animation done
timeBeg = -1;
timeEnd = -1;
selected = -1;
glutPostRedisplay();
return;
}
float pct = ( timeCur - timeBeg ) / static_cast< float >( timeEnd - timeBeg );
rects[ selected ].pos = glm::mix( src, dst, pct );
glutPostRedisplay();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
for( size_t i = 0; i < rects.size(); ++i )
{
if( selected == i )
glColor3ub( 255, 0, 0 );
else
glColor3ub( 255, 255, 255 );
const Rect& rect = rects[i];
glRectf( rect.pos.x, rect.pos.y, rect.pos.x + rect.dim.x, rect.pos.y + rect.dim.y );
}
glutSwapBuffers();
}
int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitWindowSize( 800, 600 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( "GLUT" );
glutMouseFunc( mouse );
glutTimerFunc( 0, timer, 0 );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}