glfwGetKey doesn't do an action in time - c++

I'm not sure where problem is.
Though, I have two modes in my application. By pressing "R" - key the modes are switching. The application-class is responsible for the entire app's demeanor. It contains the private member, the mode-flag (rotation_mode). In the key handling method I set this flag to the opposite value if the R-key has been pressed.
void Application::keyCallBack()
{
if (glfwGetKey(this->window, GLFW_KEY_ESCAPE) == GLFW_PRESS) this->setWindowShouldClose();
if (glfwGetKey(this->window, GLFW_KEY_R) == GLFW_PRESS) this->rotation_mode = !this->rotation_mode;
...
}
After, this flag uses as mode-definition. If a rotation mode is off, then we we should rotate a camera via mouse, otherwise we should rotate a model via mouse (when the left mouse button pressed), whereas the camera's direction is freezed.
...
if (this->rotation_mode)
{
std::cout << "rotation mode\n";
if (glfwGetMouseButton(this->window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS)
{
if (glfwGetKey(this->window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS)
{
std::cout << "rotate" << std::endl;
this->model.rotation_angle_x += this->y_offset * 6.0f * this->delta_time;
}
else
this->model.rotation_angle_z += this->x_offset * 6.0f * this->delta_time;
this->model.rotation_angle_y += this->y_offset * 6.0f * this->delta_time;
}
}
else
this->camera.camera_obj.ProcessMouseMovement(this->x_offset, this->y_offset);
...
Do not blame me for the implementation:)) It's not done, yet. The problem is that, when I press "R", occasionally the mode is not turning and the output "rotation mode" is still going on.
Note: I'm not using glfwSetKeyCallback, due to some implementation's troubles. I update it in the infinite while-loop.

According to the reference: "This function returns the last state reported for the...".
Possible that the states gets somehow overwritten or there is a race condition? Best would be to retrieve the input from the callback mechanism.
According to Thread Safety:
"This function must only be called from the main thread."
That's the thread where you initialized glfW and created your window. Where do you run your implementation?
Besides:
glfwGetMouseButton(this->window, GLFW_KEY_LEFT_ALT)
Can you do that? The reference lists only the 'GLFW_MOUSE_BUTTON_X'. Shouldn't that be glfWGetKey?
Edit:
I looked into the source code of glfW. The event processing function calls in case of KeyPress and KeyRelease the same function which sets the states of the window and calls the callback. Remember, after a Press there is a Release, which is handled by glfW but not by you.
The glfwGetKey function only reads the states of the specific window, which are set by the event processing function.
p.s. im under linux and i know X, so this was the place where i have done my research, how it is implemented for the other platforms, i don't know, but i think similar.

Related

Function gets called multiple times

So, inside the game loop function that tracks user input is called multiple times. I guess this happens because game loop goes like 40 iterations each second and if I hold down the key for a 0.5 second, function gets called 20 times. I tried to handle this with sfml events too but it didn't work window.setKeyRepeatEnabled(false). How can I solve this?
//this gets called 20-30times
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
leftPlayerPoints++;
}
Use two boolean flags: One for checking if the key is pressed or not, and one that is used to check if the action have happened yet.
In short something like
if (key_is_pressed)
{
if (!action_have_happened)
{
// Perform action...
action_have_happened = true;
}
// Else: Action have already happened this key-press, don't do it again
}
When the key is released reset both flags (to false).
That's what exactly IsKeyPressed is suppose to do , you have to use bitmasking and make it toggle state instead of continuing pressing.
Below is code from Win32API (C++). I know SFML has different events than Win32API but Masking should work in SFML also.
BOOL IsKeyToggled(CONST INT key)
{
SHORT key_state = GetAsyncKeyState(key);
BOOL is_toggled = key_state & 0x1;
return is_toggled;
}
The main point here is key_state & 0x1; bit masking with 0x1

C++, detecting if mouse is idle-ing (short-time, 20ms)

this is my first post!
I'm writing a C++ program to control main character in Touhou Games series; i'm making it for those who have hands disabilities and can't click arrow keys, but still can use mouse.
The player should trigger Arrow Keys with mouse movements (mouse goes left and left key is pressed, and so on..). I already did that part, but the character moves as if the arrow keys were pressed multiple times, so the character movements are a little clumsy and rough, not smooth and clean as if the key was HOLD.
My problem is that i have to know when mouse is idling/not moving (to understand how long the player wants to hold the arrow key -- the more the player slides the mouse in a direction, the more that arrow key is hold), but can't figure out how. Searching on Stackoverflow i've found GetLastInput function, but it triggers for EVERY input, and is not mouse-only related.
It should come out something like:
while( *mousenotidling* )
{
//holdbutton
}
What would you suggest? How can i know when mouse is idling (for short-times, like 20ms)? (or if you suggest other solutions, every opinion is welcomed)
I'm writing it in C++, with Codeblock and GCC compiler, my OS is Windows 7 x86 :)
You can call TrackMouseEvent and set the idling time to what is desire like 2000ms for 2sec idle time. Also you can use GetLastInputInfo to get the amount of milliseconds the last key or mouse movement was performed.
DWORD GetIdleTime()
{
LASTINPUTINFO pInput;
pInput.cbSize = sizeof(LASTINPUTINFO);
if (!GetLastInputInfo(&pInput))
{
// any errors will be reported
}
// return idle time in milliseconds
return pInput.dwTime;
}
Also you can try this one suggestion
int prev_x = 0, prev_y = 0; while (1)
{int x = ..., y = ...; if (x == prev_x && y == prev_y) {mouse was moved}
else {mouse wasn't moved} prev_x = x; prev_y = y;}

Moving mouse position then back to beginning position

I'm trying to make keys move the mouse to a different position on the screen and then instantly back, at a very fast rate (50+ times per second) This is my current Code.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
int main()
{
POINT p;
for( ; ; )
{
if (GetAsyncKeyState(0x57) < 0)
{
GetCursorPos(&p);
std::cout << "W key pressed";
SetCursorPos(0, 0);
SetCursorPos(p.x, p.y);
Sleep(100);
}
}
With this code it'll just change my mouse position then update as to where it was (I don't have free movement of my mouse and just keeps it at/around 0,0) If I put Sleep(100) at the end then it works pretty consistently but every ~10 seconds my mouse will get stuck at 0,0 again, the more I put up the sleep the less this happens, but why?
edit console app in Visual Studio
See documentation for GetAsyncKeyState
Return value
Type: SHORT
If the function succeeds, the return value specifies whether the key
was pressed since the last call to GetAsyncKeyState, and whether the
key is currently up or down. If the most significant bit is set, the
key is down, and if the least significant bit is set, the key was
pressed after the previous call to GetAsyncKeyState. However, you
should not rely on this last behavior; for more information, see the
Remarks.
Example
if (GetAsyncKeyState('W') & 0x8000)
{
std::cout << "W key pressed\n";
}
SetCursorPos(0,0) moves the cursor to top-left corner, while SetCursorPos(p.x, p.y) moves the cursor back to where it was when you called GetCursorPos. You won't see any changes to the mouse position.
It is not common to use these WinAPI functions in a console program.

glutPostRedisplay is not invoking display callback until a mouse event or window resize event

From the post I get to know the functioning of glutPostRedisplay API. It is understood that this API is not calling the callback instead it just set a flag so that the main loop will call its callback next time. The pseudo code is:
void onNewFrame(int x, int y)
{
// Do calculations
std::cout << " New Frame " << endl;
glutPostRedisplay();
}
void display()
{
std::cout << " Display " << endl;
// Calculations & opengl operations
}
Here display() is the API registered with glutDisplayFunc() in main(). While executing in the console, I can see " New Frame" getting printed as expected but unable to see "Display" getting printed. The glutPostRedisplay() API would have set the flag but in my case the display() is only executed when there is a mouse event or when the window size is changed.
So why is this happening? Is it because the main loop is not getting executed untill a mouse event or window resize ?
On further investigation I found that the problem was with the capability of the computer. When I re-run the same code on high configuration PC, the re-rendering is very fast. In that case the display function is called quite often.

time delay inside recursive function in opengl

My issue is that my function does the job so quickly that i don't see the progress in the screen, here is my display function:
void showMaze(const Maze::Maze &m){
glPushMatrix();
glTranslatef(-1,1, 0);
for(int i=0;i<m.num_Y;i++)
{
for(int j=0;j<m.num_X;j++)
{
char c = m.maze[i][j];
if(c=='1'){ glColor3f(255,255,0);
glRectf(0.05, -0.05, -0.05,0.05);
}
if(c=='0'){ glColor3f(20,60,60);
glRectf(0.05, -0.05, -0.05,0.05);
}
glTranslatef(0.1,0, 0);
}
glTranslatef(-(m.num_X*0.1),-0.1, 0);
}
glPopMatrix();
}
The recursive function:
bool findPath(Maze* M, char m){
showMaze(*M);
glutPostRedisplay();
if(M->isFinish())
return true;
if (m!='s' && M->north()){
update(M, 'n');
if(isNew(M) && findPath(M, 'n') && M->isFinish()){
return true;
}
else{
M->south();
}
}
// .....
else{
return false;
}
}
void render()
{
glClear( GL_COLOR_BUFFER_BIT );
findPath(N,'z');
glutSwapBuffers();
}
In main:
glutDisplayFunc( render );
so my question is how do i get to wait few seconds ( so that i can see the progress ) whenever findpath is called, i've tried glutimeelapsed, sleep,gettickcount but none of do the job correctly.
Edit1:
when i put something like sleep() right after calling showMaze(), nothing is displayed for few seconds, then the final screen shows, am not an expert in c++, but i suppose showMaze() should be executed first, then the sleep() function, or c++ wait to execute the whole function to display results?
Edit2:
i found a solution for the problem, i took X and Y o the maze whenever they change, and stored the in two vectors, and in my drawing function i display fisrt the empty maze, then i slowly add the changed X and Y.
Nothing will be visible on the screen unless you show what you are rendering by swapping buffers (unless you're rendering to the front buffer, but that's iffy). So you can sleep for however long you like in the middle of your recursive function, but you're not going to see anything until you exit that callstack. And by then, you've drawn over everything.
So instead of merely sleeping, you need to use glutSwapBuffers in your recursive call stack when you want something to be visible.
However, this is a bad idea. The render call should not do things like sleep. The system needs your render to actually render, because the screen may need to be updated for a variety of reasons (another window revealing more of your window, etc). You should not have your render loop suspend itself like this.
Instead, what you ought to be doing is executing one segment per render loop execution, relying on glutPostRedisplay to make sure the loop keeps getting called. And you should either base your animation on the time delta between loop executions, or you should use a sleep timer to make sure that at least X time always passes between cycles.
So you need to unroll your recursive call into an iterative process.
Alternatively, if you have access to Boost.Context or Boost.Coroutine, you could use that to handle things. That way, you could keep your recursive structure. When you have rendered everything you want to display, you simply suspending your coroutine back to render, who will swap buffers and return.