Condividi tramite


Input da tastiera, mouse e controller (C++)

Questo articolo è correlato alle API native WinRT legacy. Per i nuovi progetti di app native, è consigliabile usare l'API OpenXR.

I frammenti di codice in questo articolo illustrano attualmente l'uso di C++/CX anziché C++17 conforme a C++/WinRT come usato nel modello di progetto olografico C++. I concetti sono equivalenti per un progetto C++/WinRT, anche se sarà necessario tradurre il codice.

Sottoscrivere gli eventi di input CoreWindow

Input da tastiera

Nel modello di app Windows Holographic è incluso un gestore eventi per l'input da tastiera esattamente come qualsiasi altra app UWP. L'app usa i dati di input della tastiera nello stesso modo in Windows Mixed Reality.

Da AppView.cpp:

// Register for keypress notifications.
   window->KeyDown +=
       ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &AppView::OnKeyPressed);

    …

   // Input event handlers

   void AppView::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ args)
   {
       //
       // TODO: Respond to keyboard input here.
       //
   }

Input della tastiera virtuale

Per i visori VR desktop immersive, è possibile supportare le tastiere virtuali sottoposte a rendering da Windows tramite la visualizzazione immersiva implementando CoreTextEditContext. Ciò consente a Windows di comprendere lo stato delle proprie caselle di testo di cui è stato eseguito il rendering dell'app, in modo che la tastiera virtuale possa contribuire correttamente al testo.

Per altre informazioni sull'implementazione del supporto coreTextEditContext, vedere l'esempio CoreTextEditContext.

Mouse Input

Puoi anche usare l'input del mouse, di nuovo tramite i gestori eventi di input UWP CoreWindow. Ecco come modificare il modello di app Windows Holographic per supportare i clic del mouse nello stesso modo dei movimenti premuti. Dopo aver apportato questa modifica, un clic del mouse mentre indossa un dispositivo vr immersive riposizionerà il cubo.

Nota

Le app UWP possono anche ottenere dati XY non elaborati per il mouse usando l'API MouseDevice .

Per iniziare, dichiarare un nuovo gestore OnPointerPressed in AppView.h:

protected:
       void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);

In AppView.cpp aggiungere questo codice a SetWindow:

// Register for pointer pressed notifications.
   window->PointerPressed +=
       ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &AppView::OnPointerPressed);

Inserire quindi questa definizione per OnPointerPressed nella parte inferiore del file:

void AppView::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
   {
       // Allow the user to interact with the holographic world using the mouse.
       if (m_main != nullptr)
       {
           m_main->OnPointerPressed();
       }
   }

Il gestore eventi appena aggiunto è un pass-through alla classe principale del modello. Modificare la classe principale per supportare questo pass-through. Aggiungere questa dichiarazione di metodo pubblico al file di intestazione:

// Handle mouse input.
       void OnPointerPressed();

Sarà necessaria anche questa variabile membro privato:

// Keep track of mouse input.
       bool m_pointerPressed = false;

Infine, la classe principale verrà aggiornata con una nuova logica per supportare i clic del mouse. Per iniziare, aggiungere questo gestore eventi. Assicurarsi di aggiornare il nome della classe:

void MyHolographicAppMain::OnPointerPressed()
   {
       m_pointerPressed = true;
   }

A questo punto, nel metodo Update sostituire la logica esistente per ottenere una posizione puntatore con questo:

SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput();
   SpatialPointerPose^ pose = nullptr;
   if (pointerState != nullptr)
   {
       pose = pointerState->TryGetPointerPose(currentCoordinateSystem);
   }
   else if (m_pointerPressed)
   {
       pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp);
   }
   m_pointerPressed = false;

Ricompilare e ridistribuire. Si noti che il clic del mouse riposizionerà ora il cubo nel visore VR immersive o HoloLens con mouse Bluetooth collegato.

Supporto del controller di gioco

I controller di gioco possono essere un modo divertente e pratico per consentire all'utente di controllare un'esperienza immersiva Windows Mixed Reality.

aggiungere le seguenti dichiarazioni di membro privato alla classe di intestazione per il file principale:

// Recognize gamepads that are plugged in after the app starts.
       void OnGamepadAdded(Platform::Object^, Windows::Gaming::Input::Gamepad^ args);
// Stop looking for gamepads that are unplugged.
       void OnGamepadRemoved(Platform::Object^, Windows::Gaming::Input::Gamepad^ args);
Windows::Foundation::EventRegistrationToken                     m_gamepadAddedEventToken;
       Windows::Foundation::EventRegistrationToken                     m_gamepadRemovedEventToken;
// Keeps track of a gamepad and the state of its A button.
       struct GamepadWithButtonState
       {
           Windows::Gaming::Input::Gamepad^ gamepad;
           bool buttonAWasPressedLastFrame = false;
       };
       std::vector<GamepadWithButtonState>                             m_gamepads;

Inizializzare gli eventi del game pad e tutti i game pad attualmente collegati nel costruttore per la classe principale:

// If connected, a game controller can also be used for input.
   m_gamepadAddedEventToken = Gamepad::GamepadAdded +=
       ref new EventHandler<Gamepad^>(
           bind(&$safeprojectname$Main::OnGamepadAdded, this, _1, _2)
           );
m_gamepadRemovedEventToken = Gamepad::GamepadRemoved +=
       ref new EventHandler<Gamepad^>(
           bind(&$safeprojectname$Main::OnGamepadRemoved, this, _1, _2)
           );
for (auto const& gamepad : Gamepad::Gamepads)
   {
       OnGamepadAdded(nullptr, gamepad);
   }

Aggiungere questi gestori eventi alla classe principale. Assicurarsi di aggiornare il nome della classe:

void MyHolographicAppMain::OnGamepadAdded(Object^, Gamepad^ args)
   {
       for (auto const& gamepadWithButtonState : m_gamepads)
       {
           if (args == gamepadWithButtonState.gamepad)
           {
               // This gamepad is already in the list.
               return;
           }
       }
       m_gamepads.push_back({ args, false });
   }
void MyHolographicAppMain::OnGamepadRemoved(Object^, Gamepad^ args)
   {
       m_gamepads.erase(
           std::remove_if(m_gamepads.begin(), m_gamepads.end(), [&](GamepadWithButtonState& gamepadWithState)
               {
                   return gamepadWithState.gamepad == args;
               }),
           m_gamepads.end());
   }

Infine, aggiornare la logica di input per riconoscere le modifiche nello stato del controller. In questo caso viene usata la stessa variabile m_pointerPressed descritta nella sezione precedente per l'aggiunta di eventi del mouse. Aggiungerlo al metodo Update, subito prima della posizione in cui verifica la presenza di SpatialPointerPose:

// Check for new input state since the last frame.
   for (auto& gamepadWithButtonState : m_gamepads)
   {
       bool buttonDownThisUpdate = ((gamepadWithButtonState.gamepad->GetCurrentReading().Buttons & GamepadButtons::A) == GamepadButtons::A);
       if (buttonDownThisUpdate && !gamepadWithButtonState.buttonAWasPressedLastFrame)
       {
           m_pointerPressed = true;
       }
       gamepadWithButtonState.buttonAWasPressedLastFrame = buttonDownThisUpdate;
   }
// For context.
   SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput();
   SpatialPointerPose^ pose = nullptr;
   if (pointerState != nullptr)
   {
       pose = pointerState->TryGetPointerPose(currentCoordinateSystem);
   }
   else if (m_pointerPressed)
   {
       pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp);
   }
   m_pointerPressed = false;

Non dimenticare di annullare la registrazione degli eventi durante la pulizia della classe principale:

if (m_gamepadAddedEventToken.Value != 0)
   {
       Gamepad::GamepadAdded -= m_gamepadAddedEventToken;
   }
   if (m_gamepadRemovedEventToken.Value != 0)
   {
       Gamepad::GamepadRemoved -= m_gamepadRemovedEventToken;
   }

Ricompilare e ridistribuire. È ora possibile collegare o associare un controller di gioco e usarlo per riposizionare il cubo rotante.

Vedi anche