Controladores, ponteiros e foco — MRTK2

Controladores, ponteiros e foco são conceitos de nível superior que se baseiam na base estabelecida pelo sistema de entrada principal. Juntos, eles fornecem uma grande parte do mecanismo para interagir com objetos na cena.

Controladores

Os controladores são representações de um controlador físico (6 graus de liberdade, mão articulada etc.). Eles são criados por gerentes de dispositivo e são responsáveis por se comunicar com o sistema subjacente correspondente e traduzir esses dados em dados e eventos em forma de MRTK.a

Por exemplo, na plataforma Windows Mixed Reality, o WindowsMixedRealityArticulatedHand controlador é responsável pela interfiguração com as APIs subjacentes de acompanhamento manual Windows para obter informações sobre as articulações, a pose e outras propriedades da mão. Ele é responsável por transformar esses dados em eventos relevantes do MRTK (por exemplo, chamando RaisePoseInputChanged ou RaiseHandJointsUpdated) e atualizando seu próprio estado interno para TryGetJointPose que as consultas retornem dados corretos.

Geralmente, o ciclo de vida de um controlador envolverá:

  1. Um controlador é criado por um gerenciador de dispositivos após a detecção de uma nova origem (por exemplo, o gerenciador de dispositivos detecta e começa a rastrear uma mão).

  2. No loop Update() do controlador, ele chama seu sistema de API subjacente.

  3. No mesmo loop de atualização, ele gera alterações de evento de entrada chamando diretamente para o próprio sistema de entrada principal (por exemplo, elevando HandMeshUpdated ou HandJointsUpdated).

Ponteiros e foco

Ponteiros são usados para interagir com objetos de jogo. Esta seção descreve como os ponteiros são criados, como eles são atualizados e como eles determinam os objetos que estão em foco. Ele também abordará os diferentes tipos de ponteiros existentes e os cenários em que eles estão ativos.

Categorias de ponteiro

Os ponteiros geralmente se enquadram em uma das seguintes categorias:

  • Ponteiros distantes

    Esses tipos de ponteiros são usados para interagir com objetos que estão longe do usuário (distante é definido como simplesmente "não próximo"). Esses tipos de ponteiros geralmente convertem linhas que podem ir longe no mundo e permitem que o usuário interaja e manipule objetos que não estão imediatamente ao lado deles.

  • Ponteiros próximos

    Esses tipos de ponteiros são usados para interagir com objetos próximos o suficiente para o usuário pegar, tocar e manipular. Geralmente, esses tipos de ponteiros interagem com objetos procurando objetos nas proximidades (seja fazendo raycasting em pequenas distâncias, fazendo a conversão esférica procurando objetos nas proximidades ou enumerando listas de objetos que são considerados agarráveis/tocáveis).

  • Ponteiros de teletransporte

    Esses tipos de ponteiros se conectam ao sistema de teletransporte para manipular a movimentação do usuário para o local direcionado pelo ponteiro.

Mediação de ponteiro

Como um único controlador pode ter vários ponteiros (por exemplo, a mão articulada pode ter ponteiros de interação próximos e distantes), existe um componente responsável por mediar qual ponteiro deve estar ativo.

Por exemplo, à medida que a mão do usuário se aproxima de um botão pressível, a exibição ShellHandRayPointer deve parar e a PokePointer deve ser ativada.

Isso é tratado pelo DefaultPointerMediator, que é responsável por determinar quais ponteiros estão ativos, com base no estado de todos os ponteiros. Uma das principais coisas que isso faz é desabilitar ponteiros distantes quando um ponteiro próximo estiver perto de um objeto (consulte DefaultPointerMediator).

É possível fornecer uma implementação alternativa do mediador de ponteiro alterando a PointerMediator propriedade no perfil do ponteiro.

Como desabilitar ponteiros

Como o mediador de ponteiro executa cada quadro, ele acaba controlando o estado ativo/inativo de todos os ponteiros. Portanto, se você definir a propriedade IsInteractionEnabled de um ponteiro no código, ela será substituída pelo mediador de ponteiro a cada quadro. Em vez disso, você pode especificar se os PointerBehavior ponteiros devem estar ativados ou desativados. Observe que isso só funcionará se você estiver usando o padrão FocusProvider e DefaultPointerMediator no MRTK.

Exemplo: Desabilitar raios manuais no MRTK

O código a seguir desativará os raios manuais no MRTK:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Turn off hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

O código a seguir retornará os raios manuais ao comportamento padrão no MRTK:

PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);

O código a seguir forçará os raios de mão a estarem ligados, independentemente de perto de um agarramento:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOn);

Veja PointerUtils e TurnPointersOnOff para obter mais exemplos.

FocusProvider

O FocusProvider cavalo de trabalho é responsável por iterar sobre a lista de todos os ponteiros e descobrir qual é o objeto focado para cada ponteiro.

Em cada Update() chamada, isso vai:

  1. Atualize todos os ponteiros, raycasting e fazendo a detecção de ocorrência conforme configurado pelo próprio ponteiro (por exemplo, o ponteiro da esfera pode especificar o SphereOverlap raycastMode, portanto, FocusProvider fará uma colisão baseada em esfera)

  2. Atualize o objeto focado por ponteiro (ou seja, se um objeto ganhasse foco, ele também dispararia eventos para esse objeto, se um objeto perdesse o foco, ele dispararia o foco perdido, etc.).

Configuração e ciclo de vida do ponteiro

Os ponteiros podem ser configurados na seção Ponteiros do perfil do sistema de entrada.

O tempo de vida de um ponteiro geralmente é o seguinte:

  1. Um gerenciador de dispositivos detectará a presença de um controlador. Esse gerenciador de dispositivos criará o conjunto de ponteiros associados ao controlador por meio de uma chamada para RequestPointers.

  2. O FocusProvider, em seu loop Update(), itera em todos os ponteiros válidos e executa a lógica de detecção de raios ou de ocorrência associada. Isso é usado para determinar o objeto que é focado por cada ponteiro específico.

    • Como é possível ter várias fontes de entrada ativas ao mesmo tempo (por exemplo, duas mãos ativas presentes), também é possível ter vários objetos com foco ao mesmo tempo.
  3. O gerenciador de dispositivos, ao descobrir que uma origem do controlador foi perdida, derrubará os ponteiros associados ao controlador perdido.