Get x position at start of motion and end using glutmotionfunc - c++

I want to use glutmotionfunc() to get the x position at the start of the dragging motion and the end i.e. so I can get the change in x. Is there a simple way of doing this?

I think glutmotionfunc() doesn't work the way you expect it to do.
The registered callback is not only called once, when the drag has finished. Instead it gets called every time the mouse gets moved, while the button is pushed.
The idea here is to be able to update the scene continiously for every little dragging motion.
To get the movement made between calls you have to store the values you got before.
Oh, and don't forget to mark the stored values as invalid, if meanwhile the button was released. Otherwise you will get some funny results.
So here the general idea
int old_x=0;
int old_y=0;
int valid=0;
void mouse_func (int button, int state, int x, int y) {
old_x=x;
old_y=y;
valid = state == GLUT_DOWN;
}
void motion_func (int x, int y) {
if (valid) {
int dx = old_x - x;
int dy = old_y - y;
/* do something with dx and dy */
}
old_x = x;
old_y = y;
}
Don't forget to connect both callbacks with glutMotionFunc and glutMouseFunc

Related

How to get unreal engine Touch Index type in C++?

I added touch input for my game's character. The camera moves when a player's finger is dragged across the screen. However, when the joysticks are used to move, the camera doesn't move at the same time.
When I do the same code with Blueprints the code works and the camera still moves. When I drag the touch while pressing the joystick to move, I think that there is a problem in the ETouchIndex::Type. This is because in the BP when I use the finger index given in the touch event, it works. However, when I only use touch 1 as the finger index, it does not work. I think if I put that index in my CPP code it will work too, but where can I find the finger index? Can anyone please help me?
//here's my touch code that executes every tick.
FVector2D TouchLocation;
APlayerController* ActivePlayerController = UGameplayStatics::GetPlayerController(this, 0);
ActivePlayerController->GetInputTouchState(TouchType, TouchLocation.X, TouchLocation.Y, IsTouched);
if (!IsTouched)
{
DidOnce = false;
}
if (IsTouchMoved())
{
if (!DidOnce)
{
ActivePlayerController->GetInputTouchState(TouchType, PrevX, PrevY, IsTouched);
DidOnce = true;
}
ActivePlayerController->GetInputTouchState(TouchType, X, Y, IsTouched);
float FinalRotYaw = (X - PrevX) * UGameplayStatics::GetWorldDeltaSeconds(this) * 20;
float FinalRotPitch = (Y - PrevY) * UGameplayStatics::GetWorldDeltaSeconds(this) * 20;
AddControllerYawInput(FinalRotYaw);
AddControllerPitchInput(FinalRotPitch);
ActivePlayerController->GetInputTouchState(TouchType, PrevX, PrevY, IsTouched);
}

Saving data for multiple items while navigating through list of items

I am new this type of c++/cli language and i look for some help. I develop a project about the ListBoxes, i got some codes and learn basic steps on it. But i am actually stuck on the hardest part in this project.
The project counts framenumbers and keeps it. Its just an integer number and i got next and previous buttons in my code. when people click somewhere in the image, gui gets x and y coordinates and write it to the listbox correctly. What i trying to do is, when people push the next button, framenumber increased by one and clear listbox interface and ready for get other x and y coordinates. When people pressed previous button, ListBox should show the previous framenumbers x and y coordinates.
My question is, can i keep this x and y data in somewhere and reach at will? What should i do for keep these data? Any helps or thoughts will be appreciated for me.
Thank you for your helps.
What I would do is create a class to hold the data you want to save for each frame, and stick it into a collection of some sort as the user navigates through the frames. You could keep a List or a Stack, to implement retrieving the 'previous' item, but I'd probably use a Dictionary. Make the key of the dictionary the frame number, and have the value be the class of data you're saving for each frame.
Perhaps something like this:
public ref class FrameData
{
public:
int x;
int y;
public:
FrameData(int x, int y)
{
this->x = x;
this->y = y;
}
};
Dictionary<int, FrameData^>^ savedFrameData = gcnew Dictionary<int, FrameData^>();
// When they click the next or previous button:
// Save the data for the old frame.
savedFrameData->[oldFrameNumber] = gcnew FrameData(currentX, currentY);
// Retrieve the previous data for the new frame, if found.
FrameData^ dataForNewFrame;
if (savedFrameData->TryGetValue(newFrameNumber, dataForNewFrame))
{
currentX = dataForNewFrame->x;
currentY = dataForNewFrame->y;
}
else
{
currentX = 0;
currentY = 0;
}

C++ how to drag bitmap around screen

Hi so I'm trying to make it so a little UFO bitmap (drawing/painting already taken care of) can be dragged around the screen. I can't seem to make the UFO position update and then redraw repeatedly from the MouseButtonDown() function (simplified code for mouse event handler). Any suggestions on detecting the dragging and redrawing accordingly? Code is below for relevant functions:
void MouseButtonDown(int x, int y, BOOL bLeft)
{
if (bLeft)
{
while(_bMouseMoving == true && _bMouseDragRelease == false) {
_iSaucerX = x - (_pSaucer->GetWidth() / 2);
_iSaucerY = y - (_pSaucer->GetHeight() / 2);
InvalidateRect(_pGame->GetWindow(), NULL, FALSE);
}
// Set the saucer position to the mouse position
_iSaucerX = x - (_pSaucer->GetWidth() / 2);
_iSaucerY = y - (_pSaucer->GetHeight() / 2);
}
else
{
// Stop the saucer
_iSpeedX = 0;
_iSpeedY = 0;
}
}
void MouseButtonUp(int x, int y, BOOL bLeft)
{
_bMouseDragRelease = true;
}
void MouseMove(int x, int y)
{
_bMouseMoving = true;
}
To clarify what chris said, you're only going to get the WM_xBUTTONDOWN message once, and you'll need to use that to toggle a dragging state that you can query when you recieve a WM_MOUSEMOVE message.
When you get the mouse move message during a dragging state, you'll want to invalidate the rectangle surrounding where the ufo was, and the rectangle surrounding where it is.
Invalidating a rectangle causes WM_PAINT messages, where you redraw whatever was behind the ufo, and the ufo in it's new place.
Or you could cheat and make the UFO a cursor when you're dragging :)

Detecting horizontal mouse motion with Glut/OpenGL

I'm trying to detect horizontal mouse motion with OpenGL, so, when detected, execute a glutPostRedisplay(). Problem is that scene is also redrawed on vertical mouse movement.
This is the code of the registered callbacks (note mouse_inix and mouse_iniy are global (double) variables):
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN) {
mouse_inix = (double)x;
mouse_iniy = (double)y;
}
}
void motion(int x, int y)
{
if (((double)x) != mouse_inix) {
angle += 20.0;
glutPostRedisplay();
}
}
Are you sure? It doesn't look like from the code you've posted that vertical mouse movement will trigger the glutPostRedisplay() call.
BUT, you've defined "horizontal mouse movement" very narrowly here. If you move the mouse up and down, you're almost sure to get a few pixels of horizontal movement. Maybe you could put a dead zone around the mouse to keep it from moving on every pixel. Something like:
void motion(int x, int y)
{
if ((abs(x - (int)mouse_inix) > 10) {
angle += 20.0;
glutPostRedisplay();
}
}
That's one thing that's going on here. Another is the use of "double". Since glut is returning mouse coordinates as ints, you're better off sticking with that. Trying to compare "(double)x != mouse_inix" will almost certainly be true because of the precision issues with doubles. You generally don't want to compare for exactly equal to or not equal to using floating point numbers. The use of the dead zone will negate that issue, but still, why convert to doubles if you don't need them?
I don't know if "20" is degrees or radians, but it could result in some pretty jumpy moves either way. Consider scaling the size of the move to the size of the mouse move:
void motion(int x, int y)
{
int deltaX = (abs(x - (int)mouse_inix);
if (deltaX > 10) {
angle += (double)deltaX; // or "deltaX/scaleFactor" to make it move more/less
glutPostRedisplay();
}
}
It will still only rotate one way. If you used the sign of "deltaX", you would be able to rotated both directions depending on how you moved the mouse.

Using glut to prevent the mouse from leaving the window

I'm using glut for a game right now and I'm trying to keep the mouse inside the window. This isn't a first person shooter so locking it in the center is no good. I already know about glutWarpPointer(int, int); and I've trying things that work (kinda).
I've tried having the mouse warp back to the nearest edge of the window when it leaves, this works, but for a split second you see the mouse outside of the window and teleport back in. I don't want that, I want it to seem like the mouse just hits the edge of the window and stops going any further in that direction, while keeping movement in any other available direction. Like you would expect it to work.
This is not exactly an answer to your question, but it is an answer to your problem!
Almost every game has its own cursors. They would hide the mouse, and draw the cursor manually where the mouse should be positioned.
If you get your own cursor image and do as I said, you can simply draw the curser at the edge of the screen, even though the mouse position reads out of boundaries. Then you can warp the mouse back in.
Tried to search and figure this out and couldn't find an answer, so I implemented it myself. Here is what worked for my first person camera case:
callback from glutPassiveMotion
CODE SAMPLE
void Game::passiveMouseMotion(int x, int y)
{
//of my code for doing the cam, yours is may be different, this is based on the example from https://learnopengl.com/Getting-started/Camera
if (firstMouse) {
lastX = x;
lastY = y;
firstMouse = false;
}
float xoffset = x - lastX;
float yoffset = lastY - y; // reversed since y-coordinates go from bottom to top
lastX = x;
lastY = y;
camera->ProcessMouseMovement(xoffset, yoffset);
glutPostRedisplay();
//this is the main thing that keeps it from leaving the screen
if ( x < 100 || x > win_w - 100 ) { //you can use values other than 100 for the screen edges if you like, kind of seems to depend on your mouse sensitivity for what ends up working best
lastX = win_w/2; //centers the last known position, this way there isn't an odd jump with your cam as it resets
lastY = win_h/2;
glutWarpPointer(win_w/2, win_h/2); //centers the cursor
} else if (y < 100 || y > win_h - 100) {
lastX = win_w/2;
lastY = win_h/2;
glutWarpPointer(win_w/2, win_h/2);
}
}
Hope this helps!