Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
Input Handling

Input handling has two layers. Input::XrInputHandler samples raw OpenXR state, and Input::InputManager exposes named actions for gameplay code.

Use Input::InputManager from actors and components. Use Input::XrInputHandler only when adding a new device binding or raw OpenXR action.

Source Files

Frame Order

Input is sampled once per frame before logic tick.

xrInputHandler->syncInputs(...)
inputManager->beginFrame()
GameModule::preTick()
ITickable::preTick()
GameModule::tick(deltaTime)
ITickable::tick(deltaTime) with priority > TrackedPoseStep
xrRig->resolveTrackedPoses()
inputManager->dispatchCallbacks()
ITickable::tick(deltaTime) with priority <= TrackedPoseStep
GameModule::postTick()
ITickable::postTick()

Callbacks dispatch after XrRig resolves tracked poses. Callback code can read current-frame world-space hand poses.

Polling reads the sampled input snapshot for the current frame. Poll from tick() when the code needs continuous values.

Built-In XR Actions

The engine binds these actions in Engine::EngineKern::createInputManager().

Action Type Value
Input::Actions::XrLeftTrigger float Left trigger value, 0.0 to 1.0
Input::Actions::XrRightTrigger float Right trigger value, 0.0 to 1.0
Input::Actions::XrLeftGrip float Left grip value, 0.0 to 1.0
Input::Actions::XrRightGrip float Right grip value, 0.0 to 1.0
Input::Actions::XrLeftThumbstick glm::vec2 Left thumbstick axis
Input::Actions::XrRightThumbstick glm::vec2 Right thumbstick axis

Action Types

Input::InputManager supports three value types.

Type Bind method Poll method Callback method
bool bindBoolAction() getBoolAction() onBoolAction()
float bindFloatAction() getFloatAction() onFloatAction()
glm::vec2 bindVec2Action() getVec2Action() onVec2Action()

Boolean actions also have edge helpers:

inputManager->onBoolPressed("Action.Name", []() { /* pressed */ });
inputManager->onBoolReleased("Action.Name", []() { /* released */ });

Dispatch Rules

Rule bool float glm::vec2
EveryFrame Dispatches every frame Dispatches every frame Dispatches every frame
Changed Dispatches when value changes Dispatches when value changes by more than 0.0001 Dispatches when squared delta is greater than 0.000001
Pressed Dispatches on false-to-true edge Not used Not used
Released Dispatches on true-to-false edge Not used Not used

Use bool actions for edges. Derive them from analog inputs when the game needs thresholds.

Register A Gameplay Action

Register gameplay actions in beginPlay(). Remove callback handles in endPlay().

class WindBenderCharacter : public PlayerActor
{
public:
void beginPlay() override;
void endPlay() override;
private:
static constexpr const char* ShootAction = "WindBender.Shoot";
Input::InputManager* inputManager_ = nullptr;
};
void WindBenderCharacter::beginPlay()
{
PlayerActor::beginPlay();
inputManager_ = engine != nullptr ? engine->getInputManager() : nullptr;
if (inputManager_ == nullptr) {
return;
}
inputManager_->bindBoolAction(
ShootAction,
[this]()
{
return inputManager_ != nullptr &&
inputManager_->getFloatAction(Input::Actions::XrRightTrigger) > 0.75f;
}
);
shootCallback_ = inputManager_->onBoolPressed(
ShootAction,
[this]()
{
shoot();
}
);
}
void WindBenderCharacter::endPlay()
{
if (inputManager_ != nullptr) {
inputManager_->removeCallback(shootCallback_);
shootCallback_ = {};
inputManager_ = nullptr;
}
PlayerActor::endPlay();
}
Input::InputManager * getInputManager() const
Getter for the unified input action manager.
Definition Engine.h:119
static EngineManager & getInstance()
gets a reference to the engine manager
EngineKern * getEngineModule()
gets the pointer to the engine object
void bindBoolAction(std::string name, BoolProvider provider)
constexpr const char * XrRightTrigger

Poll Continuous Values

Use polling for movement, aiming, charging, and debug UI.

void MyActor::tick(double deltaTimeSeconds)
{
Actor::tick(deltaTimeSeconds);
Input::InputManager* input = engine != nullptr ? engine->getInputManager() : nullptr;
if (input == nullptr) {
return;
}
const glm::vec2 move = input->getVec2Action(Input::Actions::XrRightThumbstick);
const float grip = input->getFloatAction(Input::Actions::XrRightGrip);
// Apply movement or charging logic here.
}
float getFloatAction(const std::string &name) const
glm::vec2 getVec2Action(const std::string &name) const
constexpr const char * XrRightThumbstick
constexpr const char * XrRightGrip

Use Hand Poses In Callbacks

Callbacks dispatch after XrRig resolves tracked poses. Read hand poses from XrRig, not from XrInputHandler.

void WindBenderCharacter::shoot()
{
Input::XrRig* xrRig = engine != nullptr ? engine->getXrRig() : nullptr;
if (xrRig == nullptr) {
return;
}
if (!rightHand.isValid) {
return;
}
const glm::vec3 spawnPosition = rightHand.position;
const glm::quat spawnOrientation = rightHand.orientation;
}
Input::XrRig * getXrRig() const
Getter for the resolved XR rig poses.
Definition Engine.h:125
TrackedHandPose getHandPose(Hand hand) const
glm::quat orientation
Definition XrRig.h:21
glm::vec3 position
Definition XrRig.h:20

Binding Custom Actions

Actions are named strings. Use a subsystem prefix to avoid collisions.

inputManager->bindFloatAction(
"Glider.LeftGrip",
[inputManager]()
{
return inputManager->getFloatAction(Input::Actions::XrLeftGrip);
}
);
constexpr const char * XrLeftGrip

Bindings are providers. beginFrame() calls each provider and stores previous and current values.

Do not capture temporary objects in providers or callbacks. Remove callbacks when the owning actor ends play.

Ownership

Engine::EngineKern owns the input objects.

Input::XrInputHandler* EngineKern::getXrInputHandler() const;
Input::InputManager* EngineKern::getInputManager() const;
Input::XrRig* EngineKern::getXrRig() const;
Handles OpenXR input actions and controller state.

Actors store raw pointers only as cached access. They do not delete input objects.

Related Documentation