Entrada de teclado, mouse e controlador (C++)

Este artigo refere-se às APIs nativas do WinRT herdadas. Para novos projetos de aplicativos nativos, recomendamos usar a API OpenXR.

Os snippets de código neste artigo demonstram atualmente o uso do C++/CX em vez do C++17 compatível com C++/WinRT, conforme usado no modelo de projeto holográfico do C++. Os conceitos são equivalentes a um projeto C++/WinRT, embora você precise traduzir o código.

Assinar eventos de entrada CoreWindow

Entrada por teclado

No modelo de aplicativo Do Windows Holographic, incluímos um manipulador de eventos para entrada de teclado, assim como qualquer outro aplicativo UWP. Seu aplicativo consome dados de entrada de teclado da mesma maneira em Windows Mixed Reality.

Em 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.
       //
   }

Entrada de teclado virtual

Para headsets de área de trabalho imersiva, você pode dar suporte a teclados virtuais renderizados pelo Windows em sua exibição imersiva implementando CoreTextEditContext. Isso permite que o Windows entenda o estado de suas próprias caixas de texto renderizadas pelo aplicativo, para que o teclado virtual possa contribuir corretamente para o texto lá.

Para obter mais informações sobre como implementar o suporte a CoreTextEditContext, consulte o exemplo CoreTextEditContext.

Entrada por mouse

Você também pode usar a entrada do mouse, novamente por meio dos manipuladores de eventos de entrada UWP CoreWindow. Veja como modificar o modelo de aplicativo Do Windows Holographic para dar suporte a cliques do mouse da mesma forma que gestos pressionados. Depois de fazer essa modificação, um clique do mouse ao usar um dispositivo de headset imersivo reposicionará o cubo.

Observação

Os aplicativos UWP também podem obter dados XY brutos para o mouse usando a API MouseDevice .

Comece declarando um novo manipulador OnPointerPressed em AppView.h:

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

Em AppView.cpp, adicione este código a SetWindow:

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

Em seguida, coloque essa definição para OnPointerPressed na parte inferior do arquivo:

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();
       }
   }

O manipulador de eventos que acabamos de adicionar é uma passagem para o modelo main classe. Vamos modificar a classe main para dar suporte a essa passagem. Adicione essa declaração de método público ao arquivo de cabeçalho:

// Handle mouse input.
       void OnPointerPressed();

Você também precisará dessa variável de membro privado:

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

Por fim, atualizaremos a classe main com uma nova lógica para dar suporte a cliques do mouse. Comece adicionando esse manipulador de eventos. Atualize o nome da classe:

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

Agora, no método Update, substitua a lógica existente para obter uma pose de ponteiro com isso:

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;

Recompile e reimplante. Observe que o clique do mouse agora reposicionará o cubo no headset imersivo ou no HoloLens com o mouse bluetooth anexado.

Suporte ao controlador de jogo

Os controladores de jogos podem ser uma maneira divertida e conveniente de permitir que o usuário controle uma experiência imersiva Windows Mixed Reality.

adicione as seguintes declarações de membro privado à classe de cabeçalho do arquivo main:

// 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;

Inicialize eventos de gamepad e quaisquer gamepads anexados no momento no construtor para sua classe main:

// 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);
   }

Adicione esses manipuladores de eventos à classe main. Atualize o nome da 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());
   }

Por fim, atualize a lógica de entrada para reconhecer alterações no estado do controlador. Aqui, usamos a mesma variável m_pointerPressed discutida na seção acima para adicionar eventos do mouse. Adicione isso ao método Update, logo antes de onde ele verifica o 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;

Não se esqueça de cancelar o registro dos eventos ao limpar a classe main:

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

Recompile e reimplante. Agora você pode anexar ou emparelhar um controlador de jogo e usá-lo para reposicionar o cubo giratório.

Confira também