HoloLens (1.ª geração) Entrada 211: Gesto
Importante
Os tutoriais da Academia Mixed Reality foram concebidos com HoloLens (1.ª geração), Unity 2017 e Mixed Reality Headsets Envolventes em mente. Como tal, consideramos importante deixar estes tutoriais em vigor para os programadores que ainda procuram orientações no desenvolvimento desses dispositivos. Estes tutoriais não serão atualizados com os conjuntos de ferramentas ou interações mais recentes utilizados para HoloLens 2 e poderão não ser compatíveis com versões mais recentes do Unity. Serão mantidos para continuar a trabalhar nos dispositivos suportados. Foi publicada uma nova série de tutoriais para HoloLens 2.
Os gestos transformam a intenção do utilizador em ação. Com gestos, os utilizadores podem interagir com hologramas. Neste curso, vamos aprender a controlar as mãos do utilizador, responder à entrada do utilizador e dar feedback ao utilizador com base no estado e na localização manual.
No MR Basics 101, utilizámos um simples gesto de toque de ar para interagir com os nossos hologramas. Agora, vamos ultrapassar o gesto de toque de ar e explorar novos conceitos para:
- Detete quando a mão do utilizador está a ser controlada e forneça feedback ao utilizador.
- Utilize um gesto de navegação para rodar os nossos hologramas.
- Forneça feedback quando a mão do utilizador estiver prestes a ficar fora de vista.
- Utilize eventos de manipulação para permitir que os utilizadores movam hologramas com as mãos.
Neste curso, vamos revisitar o Explorador de Modelos do projeto Unity, que criámos no MR Input 210. O nosso amigo astronauta está de volta para nos ajudar na exploração destes novos conceitos de gestos.
Importante
Os vídeos incorporados em cada um dos capítulos abaixo foram gravados com uma versão mais antiga do Unity e do Mixed Reality Toolkit. Embora as instruções passo a passo sejam precisas e atuais, poderá ver scripts e elementos visuais nos vídeos correspondentes desatualizados. Os vídeos permanecem incluídos para a posteridade e porque os conceitos abrangidos ainda se aplicam.
Suporte de dispositivos
Curso | HoloLens | Auscultadores envolventes |
---|---|---|
Mr Input 211: Gesto | ✔️ | ✔️ |
Antes de começar
Pré-requisitos
- Um PC Windows 10 configurado com as ferramentas corretas instaladas.
- Alguma capacidade de programação C# básica.
- Devia ter concluído o MR Basics 101.
- Deverá ter concluído o MR Input 210.
- Um dispositivo HoloLens configurado para desenvolvimento.
Ficheiros de projeto
- Transfira os ficheiros necessários para o projeto. Requer o Unity 2017.2 ou posterior.
- Anuir o arquivo dos ficheiros no ambiente de trabalho ou noutra localização fácil de alcançar.
Nota
Se quiser ver o código fonte antes de transferir, este estará disponível no GitHub.
Errata e Notas
- "Ativar o Just My Code" tem de ser desativado (desmarcado) no Visual Studio em Ferramentas-Opções-Depuração>> para atingir pontos de interrupção no seu código.
Capítulo 0 - Configuração do Unity
Instruções
- Inicie o Unity.
- Selecione Abrir.
- Navegue para a pasta Gesto que desaproveiu anteriormente.
- Localize e selecione a pasta Iniciar/Explorador de Modelos .
- Clique no botão Selecionar Pasta .
- No painel Projeto , expanda a pasta Cenas .
- Faça duplo clique na cena ModelExplorer para carregá-la no Unity.
Edifício
- No Unity, selecione Definições de Compilação de Ficheiros>.
- Se Scenes/ModelExplorer não estiver listado em Cenas Na Compilação, clique em Adicionar Cenas Abertas para adicionar a cena.
- Se estiver a desenvolver especificamente para o HoloLens, defina o Dispositivo de destino como HoloLens. Caso contrário, deixe-o em Qualquer dispositivo.
- Certifique-se de que o Tipo de Compilação está definido como D3D e que o SDK está definido como Mais Recente instalado (que deve ser o SDK 16299 ou mais recente).
- Clique em Compilar.
- Crie uma Nova Pasta com o nome "Aplicação".
- Clique apenas na pasta Aplicação .
- Prima Selecionar Pasta e o Unity começará a criar o projeto para o Visual Studio.
Quando o Unity terminar, será apresentada uma janela Explorador de Ficheiros.
- Abra a pasta Aplicação .
- Abra a ModelExplorer Visual Studio Solution.
Se estiver a implementar no HoloLens:
- Ao utilizar a barra de ferramentas superior no Visual Studio, altere o destino de Depuração para Versão e de ARM para x86.
- Clique na seta pendente junto ao botão Máquina Local e selecione Máquina Remota.
- Introduza o endereço IP do dispositivo HoloLens e defina o Modo de Autenticação como Universal (Protocolo Não Encriptado). Clique em Selecionar. Se não souber o endereço IP do seu dispositivo, consulte Definições Rede & Opções Avançadas > da Internet>.
- Na barra de menus superior, clique em Depurar –> Iniciar Sem depuração ou prima Ctrl + F5. Se esta for a primeira vez que implementa no seu dispositivo, terá de o emparelhar com o Visual Studio.
- Quando a aplicação tiver sido implementada, dispense a Caixa de Ajuste com um gesto de seleção.
Se estiver a ser implementado num headset envolvente:
- Ao utilizar a barra de ferramentas superior no Visual Studio, altere o destino de Depuração para Versão e de ARM para x64.
- Certifique-se de que o destino de implementação está definido como Máquina Local.
- Na barra de menus superior, clique em Depurar –> Iniciar Sem depuração ou prima Ctrl + F5.
- Quando a aplicação tiver sido implementada, dispense o Fitbox ao puxar o acionador num controlador de movimento.
Nota
Poderá reparar em alguns erros vermelhos no painel Erros do Visual Studio. É seguro ignorá-los. Mude para o painel Saída para ver o progresso real da compilação. Os erros no painel Saída exigirão que efetue uma correção (na maioria das vezes, são causados por um erro num script).
Capítulo 1 - Comentários detetados à mão
Objetivos
- Subscreva eventos de controlo manual.
- Utilize o feedback do cursor para mostrar aos utilizadores quando uma mão está a ser controlada.
Nota
No HoloLens 2 , as mãos detetaram incêndios sempre que as mãos estão visíveis (não apenas quando um dedo está a apontar para cima).
Instruções
- No painel Hierarquia , expanda o objeto InputManager .
- Procure e selecione o objeto GesturesInput .
O script InteractionInputSource.cs executa estes passos:
- Subscreve os eventos InteractionSourceDetected e InteractionSourceLost.
- Define o estado HandDetected.
- Anule a subscrição dos eventos InteractionSourceDetected e InteractionSourceLost.
Em seguida, iremos atualizar o nosso cursor do MR Input 210 para um que mostre feedback consoante as ações do utilizador.
- No painel Hierarquia , selecione o objeto Cursor e elimine-o.
- No painel Projeto , procure CursorWithFeedback e arraste-o para o painel Hierarquia .
- Clique em InputManager no painel Hierarquia e, em seguida, arraste o objeto CursorWithFeedback da Hierarquia para o campo CursorsimpleSinglePointerSelector do InputManager, na parte inferior do Inspetor.
- Clique no CursorWithFeedback na Hierarquia.
- No painel Inspetor , expanda Dados de Estado do Cursor no script cursor de objeto .
Os Dados de Estado do Cursor funcionam da seguinte forma:
- Qualquer estado Observar significa que não foi detetada nenhuma mão e que o utilizador está simplesmente a olhar à volta.
- Qualquer estado de Interação significa que é detetado um comando ou mão.
- Qualquer estado hover significa que o utilizador está a olhar para um holograma.
Criar e Implementar
- No Unity, utilize as Definições de Compilação de Ficheiros > para reconstruir a aplicação.
- Abra a pasta Aplicação .
- Se ainda não estiver aberto, abra o ModelExplorer Visual Studio Solution.
- (Se já tiver criado/implementado este projeto no Visual Studio durante a configuração, pode abrir essa instância do VS e clicar em "Recarregar Tudo" quando lhe for pedido).
- No Visual Studio, clique em Depurar –> Iniciar Sem depuração ou prima Ctrl + F5.
- Depois de a aplicação ser implementada no HoloLens, dispense a caixa de ajuste com o gesto de toque de ar.
- Mova a mão para a vista e aponte o dedo indicador para o céu para iniciar o controlo manual.
- Mova a mão para a esquerda, para a direita, para cima e para baixo.
- Veja como o cursor muda quando a sua mão é detetada e, em seguida, perdida da vista.
- Se estiver a utilizar um headset envolvente, terá de ligar e desligar o controlador. Este feedback torna-se menos interessante num dispositivo envolvente, uma vez que um controlador ligado estará sempre "disponível".
Capítulo 2 - Navegação
Objetivos
- Utilize eventos de gesto de navegação para rodar o astronauta.
Instruções
Para utilizar gestos de Navegação na nossa aplicação, vamos editar GestureAction.cs para rodar objetos quando o gesto de Navegação ocorrer. Além disso, iremos adicionar feedback ao cursor para apresentar quando a Navegação estiver disponível.
- No painel Hierarquia , expanda CursorWithFeedback.
- Na pasta Hologramas , localize o recurso ScrollFeedback .
- Arraste e largue a prefab ScrollFeedback no CursorWithFeedback GameObject na Hierarquia.
- Clique em CursorWithFeedback.
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa CursorFeedback. Selecione o resultado da pesquisa.
- Arraste e largue o objeto ScrollFeedback da Hierarquia para a propriedade Objeto de Jogo Detetado de Deslocamento no componente Feedback do Cursor no Inspetor.
- No painel Hierarquia , selecione o objeto AstroMan .
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa Ação de Gesto. Selecione o resultado da pesquisa.
Em seguida, abra GestureAction.cs no Visual Studio. No exercício de codificação 2.c, edite o script para fazer o seguinte:
- Rode o objeto AstroMan sempre que for efetuado um gesto de Navegação.
- Calcule o rotationFactor para controlar a quantidade de rotação aplicada ao objeto.
- Rode o objeto à volta do eixo y quando o utilizador mover a mão para a esquerda ou para a direita.
Conclua os exercícios de codificação 2.c no script ou substitua o código pela solução concluída abaixo:
using HoloToolkit.Unity.InputModule;
using UnityEngine;
/// <summary>
/// GestureAction performs custom actions based on
/// which gesture is being performed.
/// </summary>
public class GestureAction : MonoBehaviour, INavigationHandler, IManipulationHandler, ISpeechHandler
{
[Tooltip("Rotation max speed controls amount of rotation.")]
[SerializeField]
private float RotationSensitivity = 10.0f;
private bool isNavigationEnabled = true;
public bool IsNavigationEnabled
{
get { return isNavigationEnabled; }
set { isNavigationEnabled = value; }
}
private Vector3 manipulationOriginalPosition = Vector3.zero;
void INavigationHandler.OnNavigationStarted(NavigationEventData eventData)
{
InputManager.Instance.PushModalInputHandler(gameObject);
}
void INavigationHandler.OnNavigationUpdated(NavigationEventData eventData)
{
if (isNavigationEnabled)
{
/* TODO: DEVELOPER CODING EXERCISE 2.c */
// 2.c: Calculate a float rotationFactor based on eventData's NormalizedOffset.x multiplied by RotationSensitivity.
// This will help control the amount of rotation.
float rotationFactor = eventData.NormalizedOffset.x * RotationSensitivity;
// 2.c: transform.Rotate around the Y axis using rotationFactor.
transform.Rotate(new Vector3(0, -1 * rotationFactor, 0));
}
}
void INavigationHandler.OnNavigationCompleted(NavigationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void INavigationHandler.OnNavigationCanceled(NavigationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void IManipulationHandler.OnManipulationStarted(ManipulationEventData eventData)
{
if (!isNavigationEnabled)
{
InputManager.Instance.PushModalInputHandler(gameObject);
manipulationOriginalPosition = transform.position;
}
}
void IManipulationHandler.OnManipulationUpdated(ManipulationEventData eventData)
{
if (!isNavigationEnabled)
{
/* TODO: DEVELOPER CODING EXERCISE 4.a */
// 4.a: Make this transform's position be the manipulationOriginalPosition + eventData.CumulativeDelta
}
}
void IManipulationHandler.OnManipulationCompleted(ManipulationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void IManipulationHandler.OnManipulationCanceled(ManipulationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void ISpeechHandler.OnSpeechKeywordRecognized(SpeechEventData eventData)
{
if (eventData.RecognizedText.Equals("Move Astronaut"))
{
isNavigationEnabled = false;
}
else if (eventData.RecognizedText.Equals("Rotate Astronaut"))
{
isNavigationEnabled = true;
}
else
{
return;
}
eventData.Use();
}
}
Irá reparar que os outros eventos de navegação já estão preenchidos com algumas informações. Emitemos o GameObject para a pilha modal inputSystem do Toolkit, para que o utilizador não tenha de manter o foco no Astronauta assim que a rotação tiver começado. Correspondentemente, tiramos o GameObject da pilha assim que o gesto estiver concluído.
Criar e Implementar
- Recrie a aplicação no Unity e, em seguida, crie e implemente a partir do Visual Studio para executá-la no HoloLens.
- Olhe para o astronauta, devem aparecer duas setas em ambos os lados do cursor. Este novo elemento visual indica que o astronauta pode ser rodado.
- Coloque a mão na posição pronta (dedo indicador apontado para o céu) para que o HoloLens comece a controlar a sua mão.
- Para rodar o astronauta, reduza o dedo indicador para uma posição de aproximar os dedos e, em seguida, mova a mão para a esquerda ou para a direita para acionar o gesto NavigationX.
Capítulo 3 - Orientação Manual
Objetivos
- Utilize a classificação de orientação manual para ajudar a prever quando o controlo manual será perdido.
- Forneça feedback sobre o cursor para mostrar quando a mão do utilizador se aproxima da margem de vista da câmara.
Instruções
- No painel Hierarquia , selecione o objeto CursorWithFeedback .
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa Orientação Manual. Selecione o resultado da pesquisa.
- Na pasta Hologramas do painel Projeto, localize o recurso HandGuidanceFeedback.
- Arraste e largue o recurso HandGuidanceFeedback na propriedade Indicador de Orientação Manual no painel Inspetor .
Criar e Implementar
- Recrie a aplicação no Unity e, em seguida, crie e implemente a partir do Visual Studio para experimentar a aplicação no HoloLens.
- Coloque a sua mão à vista e levante o dedo indicador para ser controlado.
- Comece a rodar o astronauta com o gesto de Navegação (aproxime o dedo indicador e o polegar).
- Mova a mão para a esquerda, para a direita, para cima e para baixo.
- À medida que a sua mão se aproxima da extremidade da moldura do gesto, deverá ser apresentada uma seta junto ao cursor para o avisar de que o controlo manual será perdido. A seta indica a direção para mover a mão para evitar que o controlo seja perdido.
Capítulo 4 - Manipulação
Objetivos
- Utilize eventos de manipulação para mover o astronauta com as mãos.
- Forneça feedback sobre o cursor para informar o utilizador sobre quando é que a Manipulação pode ser utilizada.
Instruções
GestureManager.cs e AstronautManager.cs permitir-nos-ão fazer o seguinte:
- Utilize a palavra-chave de voz "Mover Astronauta" para ativar gestos de manipulação e "Rodar Astronauta" para desativá-los.
- Mude para responder ao Reconhecedor de Gestos de Manipulação.
Vamos começar.
- No painel Hierarquia , crie um novo GameObject vazio. Dê-lhe o nome "AstronautManager".
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa Gestor de Astronautas. Selecione o resultado da pesquisa.
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa Origem de Entrada de Voz. Selecione o resultado da pesquisa.
Vamos agora adicionar os comandos de voz necessários para controlar o estado de interação do astronauta.
- Expanda a secção Palavras-chave no Inspetor.
- Clique no + lado direito para adicionar uma nova palavra-chave.
- Escreva a Palavra-chave como Mover Astronauta. Não hesite em adicionar um Atalho de Tecla, se assim o desejar.
- Clique no + lado direito para adicionar uma nova palavra-chave.
- Escreva a Palavra-chave como Rodar Astronauta. Não hesite em adicionar um Atalho de Tecla, se assim o desejar.
- O código do processador correspondente pode ser encontrado em GestureAction.cs, no processador ISpeechHandler.OnSpeechKeywordRecognized .
Em seguida, vamos configurar o feedback de manipulação no cursor.
- Na pasta Hologramas do painel Do Projeto, localize o recurso PathingFeedback.
- Arraste e largue a prefab PathingFeedback no objeto CursorWithFeedback na Hierarquia.
- No painel Hierarquia , clique em CursorWithFeedback.
- Arraste e largue o objeto PathingFeedback da Hierarquia para a propriedade Objeto de Jogo Detetado de Caminho no componente Feedback do Cursor no Inspetor.
Agora, temos de adicionar código a GestureAction.cs para ativar o seguinte:
- Adicione código à função IManipulationHandler.OnManipulationUpdated , que irá mover o astronauta quando for detetado um gesto de Manipulação .
- Calcule o vetor de movimento para determinar para onde o astronauta deve ser movido com base na posição da mão.
- Mover o astronauta para a nova posição.
Conclua o exercício de codificação 4.a em GestureAction.cs ou utilize a nossa solução concluída abaixo:
using HoloToolkit.Unity.InputModule;
using UnityEngine;
/// <summary>
/// GestureAction performs custom actions based on
/// which gesture is being performed.
/// </summary>
public class GestureAction : MonoBehaviour, INavigationHandler, IManipulationHandler, ISpeechHandler
{
[Tooltip("Rotation max speed controls amount of rotation.")]
[SerializeField]
private float RotationSensitivity = 10.0f;
private bool isNavigationEnabled = true;
public bool IsNavigationEnabled
{
get { return isNavigationEnabled; }
set { isNavigationEnabled = value; }
}
private Vector3 manipulationOriginalPosition = Vector3.zero;
void INavigationHandler.OnNavigationStarted(NavigationEventData eventData)
{
InputManager.Instance.PushModalInputHandler(gameObject);
}
void INavigationHandler.OnNavigationUpdated(NavigationEventData eventData)
{
if (isNavigationEnabled)
{
/* TODO: DEVELOPER CODING EXERCISE 2.c */
// 2.c: Calculate a float rotationFactor based on eventData's NormalizedOffset.x multiplied by RotationSensitivity.
// This will help control the amount of rotation.
float rotationFactor = eventData.NormalizedOffset.x * RotationSensitivity;
// 2.c: transform.Rotate around the Y axis using rotationFactor.
transform.Rotate(new Vector3(0, -1 * rotationFactor, 0));
}
}
void INavigationHandler.OnNavigationCompleted(NavigationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void INavigationHandler.OnNavigationCanceled(NavigationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void IManipulationHandler.OnManipulationStarted(ManipulationEventData eventData)
{
if (!isNavigationEnabled)
{
InputManager.Instance.PushModalInputHandler(gameObject);
manipulationOriginalPosition = transform.position;
}
}
void IManipulationHandler.OnManipulationUpdated(ManipulationEventData eventData)
{
if (!isNavigationEnabled)
{
/* TODO: DEVELOPER CODING EXERCISE 4.a */
// 4.a: Make this transform's position be the manipulationOriginalPosition + eventData.CumulativeDelta
transform.position = manipulationOriginalPosition + eventData.CumulativeDelta;
}
}
void IManipulationHandler.OnManipulationCompleted(ManipulationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void IManipulationHandler.OnManipulationCanceled(ManipulationEventData eventData)
{
InputManager.Instance.PopModalInputHandler();
}
void ISpeechHandler.OnSpeechKeywordRecognized(SpeechEventData eventData)
{
if (eventData.RecognizedText.Equals("Move Astronaut"))
{
isNavigationEnabled = false;
}
else if (eventData.RecognizedText.Equals("Rotate Astronaut"))
{
isNavigationEnabled = true;
}
else
{
return;
}
eventData.Use();
}
}
Criar e Implementar
- Reconstrua no Unity e, em seguida, crie e implemente a partir do Visual Studio para executar a aplicação no HoloLens.
- Mova a mão para a frente do HoloLens e levante o dedo indicador para que possa ser monitorizado.
- Concentre o cursor sobre o astronauta.
- Diga "Mover Astronauta" para mover o astronauta com um gesto de Manipulação.
- Devem ser apresentadas quatro setas à volta do cursor para indicar que o programa irá agora responder a eventos de Manipulação.
- Baixe o dedo indicador para baixo até ao polegar e mantenha-os apertados.
- À medida que move a mão, o astronauta também se move (isto é Manipulação).
- Levante o dedo indicador para parar de manipular o astronauta.
- Nota: se não disser "Mover Astronauta" antes de mover a mão, o gesto de Navegação será utilizado.
- Diga "Rodar Astronauta" para regressar ao estado rotativo.
Capítulo 5 - Expansão de modelos
Objetivos
- Expanda o modelo Astronauta em várias partes mais pequenas com as quais o utilizador pode interagir.
- Mova cada peça individualmente com gestos de Navegação e Manipulação.
Instruções
Nesta secção, vamos realizar as seguintes tarefas:
- Adicione uma nova palavra-chave "Expandir Modelo" para expandir o modelo de astronauta.
- Adicione uma nova Palavra-chave "Repor Modelo" para devolver o modelo ao formulário original.
Vamos fazê-lo ao adicionar mais duas palavras-chave à Origem de Entrada de Voz do capítulo anterior. Também vamos demonstrar outra forma de lidar com eventos de reconhecimento.
- Clique novamente em AstronautManager no Inspector e expanda a secção Palavras-chave no Inspetor.
- Clique no + lado direito para adicionar uma nova palavra-chave.
- Escreva a Palavra-chave como Expandir Modelo. Se quiser, pode adicionar um Atalho de Tecla.
- Clique no + lado direito para adicionar uma nova palavra-chave.
- Escreva a Palavra-chave como Modelo de Reposição. Se quiser, pode adicionar um Atalho de Tecla.
- No painel Inspetor , clique no botão Adicionar Componente .
- No menu, escreva na caixa de pesquisa Processador de Entrada de Voz. Selecione o resultado da pesquisa.
- Verifique Se é o Serviço de Escuta Global, uma vez que queremos que estes comandos funcionem independentemente do GameObject que estamos a focar.
- Clique no + botão e selecione Expandir Modelo na lista pendente Palavra-chave.
- Clique no + em Resposta e arraste o AstronautManager da Hierarquia para o campo Nenhum (Objeto ).
- Agora, clique na lista pendente Sem Função , selecione AstronautManager e, em seguida, ExpandModelCommand.
- Clique no botão do Processador de Entrada de + Voz e selecione Repor Modelo na lista pendente Palavra-chave.
- Clique no + em Resposta e arraste o AstronautManager da Hierarquia para o campo Nenhum (Objeto ).
- Agora, clique na lista pendente Sem Função , selecione AstronautManager e, em seguida, ResetModelCommand.
Criar e Implementar
- Experimente! Crie e implemente a aplicação no HoloLens.
- Diga Expandir Modelo para ver o modelo de astronauta expandido.
- Utilize a Navegação para rodar peças individuais do fato de astronauta.
- Diga Mover Astronauta e, em seguida, utilize Manipulação para mover peças individuais do fato de astronauta.
- Diga Rodar Astronauta para rodar as peças novamente.
- Diga Repor Modelo para devolver o astronauta à sua forma original.
O Fim
Parabéns! Concluiu agora o MR Input 211: Gesto.
- Sabe como detetar e responder a eventos de controlo manual, navegação e manipulação.
- Compreende a diferença entre gestos de Navegação e Manipulação.
- Sabe como alterar o cursor para fornecer feedback visual para quando uma mão é detetada, quando uma mão está prestes a ser perdida e para quando um objeto suporta interações diferentes (Navegação vs Manipulação).