When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
41 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
hi. i'm making a camera class that will be handling inputs, (using glfw) and in my KeyCallback, I have an array of bools for each glfw key that I set to true or false to avoid the os's repeat rate for held keys. here is the code I have for testing:
static bool held = false;
if (!held)
{
if (userActions.Keys[GLFW_KEY_SPACE].KeyState) // Check if Space is pressed
{
Logger::logger->Log("KeyDown");
held = true; // Set KeyHeld to true
}
}
else if (!(userActions.Keys[GLFW_KEY_SPACE].KeyState)) // Check if Space is not pressed IF KeyHeld is true
{
Logger::logger->Log("KeyUp");
held = false; // Set KeyHeld to false
}
here is the KeyCallback, just in case there's something I can improve about it:
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS) // Make it so holding down a key doesnt rely on the repeat rate
userActions.Keys[key].KeyState = true; // Meaning it shouldnt press once, then wait, then finally hold
if (action == GLFW_RELEASE)
userActions.Keys[key].KeyState = false;
}
i want to change it to this, where held and keystate are a struct bitfield that take up one bit each.
i have a useractions struct that is passed around with the keys, context for the previous and latter code blocks:
struct UserActions
{
KeyHandler Keys[348]{ 0, 0 };
bool MouseButtons[8]{false};
double MousePos[2]{0.0};
} userActions;
here is that KeyHandler struct:
struct KeyHandler
{
bool KeyState : 1;
bool KeyHeld : 1;
};
here is the code that doesn't currently work as intended, where instead of only recieving a log when the key becomes up or down (which is also what happens with the initial code at the top of this message), it logs every frame with the key's state. here is the working (compiles, but not intended function) code:
if (!userActions.Keys[GLFW_KEY_SPACE].KeyHeld)
{
if (userActions.Keys[GLFW_KEY_SPACE].KeyState)
{
Logger::logger->Log("KeyDown");
userActions.Keys[GLFW_KEY_SPACE].KeyHeld = true;
}
}
else if (!(userActions.Keys[GLFW_KEY_SPACE].KeyState))
{
Logger::logger->Log("KeyUp");
userActions.Keys[GLFW_KEY_SPACE].KeyHeld = false;
}
I can't figure out what's wrong with the code, because it looks about the same, can someone help?
@hollow sonnet
Please don't delete forum posts. They can be helpful to refer to later and other members can learn from them. In the future you can use !solved to close a post and mark a post as solved.
sorry, reordering posts for better reading
still having no luck :/
Having trouble with making a key that wont repeat when held, trying to use bitfields, using glfw
kind of hard to understand whats actually going on in your code without the full context. Github link or better yet a minimal example would help
sure, hold on just gotta commit it rq
useractions in here: https://github.com/fl2mex/hyper/blob/master/src/UserActions.h
keycallback in here: https://github.com/fl2mex/hyper/blob/master/src/Application.cpp
camera struct with keyboard input here: https://github.com/fl2mex/hyper/blob/master/src/Camera.h
problem is in the camera struct
I reckon its this
https://github.com/fl2mex/hyper/blob/master/src/UserActions.h
Its a global thats defined in a header so
https://github.com/fl2mex/hyper/blob/master/src/Camera.h
Defines their own userActions global. And Application.cpp
https://github.com/fl2mex/hyper/blob/master/src/Application.cpp
Also gets their own global userActions
If they ever interacted with eachother youd probably get a multiple definition error and it would blow up nicely. So since each file has their own userActions the inputs wont be consistent across files.
You can verify that by printing the address of userActions in Application.cpp and Camera.h incase Im wrong about this
problem is trying to access userActions in a static method (KeyCallback) that is used by glfw, so I cant change the method parameters
*to make userActions not static
you can declare it
// UserAction.hpp
// ...
extern UserAction userAction;
and define it in its own C++ file so every TU refers to same userAction
// User Action.cpp
#include "UserAction.hpp"
UserAction userAction{};
you could also make it inline but that doesnt scale very well
definitely not static tho that just makes it explicit that every cpp file gets their own userAction
thats probably also why your program didnt blow up when you ended up defining multiple userActions in each file
i've done that now, (and changed my useractions to non-static) but when space is being held, it logs every second in comparison of what I want it to do, which is only log when the key is pressed down and back up, while maintaining the ability to (commented out at the top of the ProcessKeyboardInput function) have input be held down without having to wait for the os to send repeated inputs in
really all i'm trying to do is figure out why I can't change this:
static bool held = false;
if (!held)
{
if (userActions.Keys[GLFW_KEY_SPACE].KeyState) // Check if Space is pressed
{
Logger::logger->Log("KeyDown");
held = true;
}
}
else if (!userActions.Keys[GLFW_KEY_SPACE].KeyState) // Check if Space is not pressed IF KeyHeld is true
{
Logger::logger->Log("KeyUp");
held = false;
}```
into this:
```cpp
if (!userActions.Keys[GLFW_KEY_SPACE].KeyHeld)
{
if (userActions.Keys[GLFW_KEY_SPACE].KeyState)
{
Logger::logger->Log("KeyDown");
userActions.Keys[GLFW_KEY_SPACE].KeyHeld = true;
}
}
else if (!userActions.Keys[GLFW_KEY_SPACE].KeyState)
{
Logger::logger->Log("KeyUp");
userActions.Keys[GLFW_KEY_SPACE].KeyHeld = false;
}```
and with what you said before, my guess is something to do with static?
(again, inside my ProcessKeyboardInput function in camera.h)
i commited changing the static useractions to extern
Can you push those changes real quick?
ahh you just declared it in Application.cpp.
You declare it in UserAction.hpp so every file knows that the global exists somewhere
extern UserAction userAction;
But you define it in a C++ file for example UserAction.cpp so userAction only actually exists once for your entire program
UserAction userAction{};
Whats also important to remember is that static means different things for functions/classes and namespace/global scope
Functions and Classes static implies that the variable exists only once. In functions you get nice guarantees about it being initialized and for classes you have to initialize it yourself in a C++ file or make it inline
Namespace/Global static means that the static variable/function is unique to that translation unit (basically everything that makes up the file you compile)
You could also look up Meyers Singletons if you want which is the most common way to design globals in C++
so i've made some changes that ive committed and pushed, including moving some camera functions to a seperate cpp file so I can put useractions in a cpp file, and also in the application.cpp file so glfw can access it, but i still get errors for redefinitions inside application.obj, alongside two unresolved external symbols inside application.obj and camera.obj
i'm still very confused ðŸ˜
i'm going to have to look at this tomorrow, it's 3am and i have uni in the morning, thank you for teaching me about externs, i hope that we can fix this later
have a good day/night
@hollow sonnet Has your question been resolved? If so, type !solved :)
Okok
You probably should drop using anonymous structs. Can be done but its usually a bad idea. Just declare UserActions and then declare your global of that type instead of doing it in one go.
Heres how Id change UserActions.h
#pragma once
namespace hyper
{
struct KeyH
{
bool KeyState : 1;
bool KeyHeld : 1;
};
struct UserActions // Having an extra header is dumb but I need it in two places
{
KeyH Keys[348]{ 0, 0 }; // I need to figure out how to get all of this as pointers
bool MouseButtons[8]{ false }; // so i'm not passing around ~0.4 KILOBYTES every time
double MousePos[2]{ 0.0 }; // I move the mouse/press keys
}; // Should declare this somewhere else more visible
extern UserActions userActions; // Declare here this gets pasted into every file that includes UserActions.h so they are aware of the globel
}
And instead of defining userActions in Application.cpp and Camera.cpp which is where the redefinition error comes from.
A global must be defined only once in a single C++ file
I suggested creating UserActions.cpp twice now because if the file is named after the class its easy to guess that the global is defined in there so you dont accidentally define it twice
You can define it there like you did in the other files
// UserActions.cpp
#include "UserActions.h"
hyper::UserActions userActions{}; // Define it only here and make sure this is the only place where this is ever defined
Dunno about the unresolved symbols. If you cant figure it out later you can always ask here again