Controladores, ponteiros e foco

Controladores, ponteiros e foco são conceitos de alto nível que se baseiam na fundação estabelecida pelo sistema de entrada central. Juntos, 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). São criados por gestores de dispositivos e são responsáveis pela comunicação com o sistema subjacente correspondente e pela tradução desses dados em dados e eventos em forma de MRTK.a

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

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

  1. Um controlador é criado por um gestor de dispositivos após a deteção de uma nova fonte (por exemplo, o gestor do dispositivo deteta e começa a rastrear uma mão).

  2. No ciclo Update do controlador, chama para o seu sistema API subjacente.

  3. No mesmo ciclo de atualização, aumenta as alterações do evento de entrada, ligando diretamente para o próprio sistema de entrada do núcleo (por exemplo, aumentando handMeshUpdated ou HandJointsUpdated).

Ponteiros e foco

Os ponteiros são usados para interagir com objetos de jogo. Esta secção descreve como os ponteiros são criados, como são atualizados e como determinam os(s) objetos que estão em foco. Abrangerá também os diferentes tipos de ponteiros existentes e os cenários em que estão ativos.

Categorias de ponteiros

Os ponteiros geralmente enquadram-se numa das seguintes categorias:

  • Ponteiros distantes

    Estes tipos de ponteiros são usados para interagir com objetos que estão longe do utilizador (longe é definido como simplesmente "não perto"). Este tipo de ponteiros geralmente lançam linhas que podem ir longe para o mundo e permitir que o utilizador interaja e manipule objetos que não estão imediatamente ao seu lado.

  • Perto de ponteiros

    Estes tipos de ponteiros são usados para interagir com objetos que estão perto o suficiente do utilizador para agarrar, tocar e manipular. Geralmente, estes tipos de ponteiros interagem com objetos procurando objetos nas proximidades (quer fazendo raycasting a pequenas distâncias, fazendo fundição esférica à procura de objetos nas proximidades, ou enumerando listas de objetos que são considerados grabbable/touchable).

  • Ponteiros de teletransporte

    Estes tipos de ponteiros ligam-se ao sistema de teletransporte para manusear a deslocação do utilizador para o local visado 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óximo e distante), existe um componente que é responsável pela mediação do ponteiro que deve estar ativo.

Por exemplo, à medida que a mão do utilizador se aproxima de um botão pressável, o ShellHandRayPointer deve parar de aparecer e o deve ser PokePointer ativado.

Isto é tratado pelo DefaultPointerMediator , que é responsável por determinar quais os ponteiros ativos, com base no estado de todos os ponteiros. Uma das coisas-chave que isto faz é desativar ponteiros distantes quando um ponteiro próximo está perto de um objeto (por favor DefaultPointerMediator ver).

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

Como desativar ponteiros

Como o mediador de ponteiro executa cada quadro, acaba por controlar o estado ativo/inativo de todos os ponteiros. Portanto, se definir a propriedade IsInteractionEnabled de um ponteiro em código, será substituída pelo mediador de ponteiro em cada frame. Em vez disso, pode especificar se os PointerBehavior ponteiros devem estar ligados ou desligados. Note que isto só funcionará se estiver a utilizar o padrão FocusProvider e DefaultPointerMediator no MRTK.

Exemplo: Desativar os raios de mão no MRTK

O seguinte código desligará os raios de mão 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 seguinte código devolverá os raios manuais ao seu comportamento padrão no MRTK:

PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);

O seguinte código forçará os raios manuais a funcionar, independentemente de se aproximarem de um grabbable:

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

Ver PointerUtils e para mais TurnPointersOnOff 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, isto será:

  1. Atualizar todos os ponteiros, através de raycasting e fazendo a deteção de batidas configurados pelo próprio ponteiro (por exemplo, o ponteiro de esfera poderia especificar o raycastMode SphereOverlap, de modo que o FocusProvider fará uma colisão baseada na esfera)

  2. Atualize o objeto focado numa base por ponteiro (isto é, se um objeto ganhar foco, também desencadearia eventos para esse objeto, se um objeto perdesse o foco, desencadearia o foco perdido, etc.

Configuração do ponteiro e ciclo de vida

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

A vida útil de um ponteiro é geralmente a seguinte:

  1. Um gestor de dispositivos detetará a presença de um controlador. Este gestor de dispositivos irá então criar o conjunto de ponteiros associados ao controlador através de uma chamada para RequestPointers .

  2. O FocusProvider, no seu ciclo Update() irá iterar sobre todos os ponteiros válidos e fazer a lógica de raycast ou deteção de sucesso associada. Isto é usado para determinar o objeto que é focado por cada ponteiro particular.

    • Como é possível ter múltiplas fontes de entrada ativas ao mesmo tempo (por exemplo, duas mãos ativas presentes), também é possível ter múltiplos objetos que se concentram ao mesmo tempo.
  3. O gestor do dispositivo, ao descobrir que uma fonte do controlador foi perdida, irá derrubar os ponteiros associados ao controlador perdido.