# Eventos de clique

Uma cena do Decentraland pode detectar ações de input de todos os botões usados para controlar o avatar do jogador. Isso inclui cliques do ponteiro, vários botões de ação e as teclas usadas para mover o avatar. Os eventos de botão podem vir de um mouse e teclado no cliente de desktop, dos controles na tela no [app mobile](/creator/content-creator-pt/scenes-sdk7/criar-para-mobile/building-for-mobile.md)de um controle VR, ou de outros dispositivos de input — todos são interpretados da mesma forma pelo SDK.

Você pode detectar ações de input em uma Entity. Isso envolve pressionar um botão enquanto o cursor do jogador está apontando para o collider dessa Entity. Você também pode detectar *global* evento de input, que envolve pressionar ativar o input a qualquer momento, sem considerar para onde o ponteiro está apontando.

{% hint style="warning" %}
**📔 Nota**: As Entities devem ter um [collider](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md) para responder às ações de input. `MeshRenderer` models também devem receber um `MeshCollider` component. Models de um `GLTFContainer` podem ter sua própria geometria de colisão embutida, ou podem ser configurados para usar sua geometria visível, também podem receber um `MeshCollider` component.
{% endhint %}

Há várias maneiras diferentes de lidar com ações de input, dependendo do caso de uso.

* [**Registrar uma callback**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md): A maneira mais fácil de adicionar interação a uma única Entity. Escreva uma única instrução para configurar uma função de callback e feedback de hover.
* [**Baseado em System**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/system-based-events.md): Ideal para lidar com várias Entities com comportamento semelhante. Use um System para iterar sobre Entities semelhantes e consultar ações de input em cada uma, tratando todas com a mesma lógica. O feedback de hover precisa ser configurado separadamente. Essa abordagem também é necessária para lidar com ações de input globais.
* [**Avançado**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/advanced-button-events.md): Leia os dados brutos da resposta em cada Entity, incluindo carimbos de data e hora e um histórico de eventos de input. Isso pode ser útil para definir padrões de interação personalizados.

## Use o Scene Editor no Creator Hub

A maneira mais fácil de lidar com eventos de clique em uma Entity é usar o Scene Editor. Use o **On Click** ou **On Input Action** Triggers em um item para chamar ações ao clicar nele. Ou use **On Global Click**, **On Global Primary** ou **On Global Secondary** Triggers para reagir a eventos globais de botão. Veja [Torne qualquer item smart](/creator/content-creator-pt/scene-editor/interatividade/make-any-item-smart.md).

## Exemplo simples

Para detectar cliques em uma Entity, use `pointerEventsSystem.onPointerDown`.

```ts
pointerEventsSystem.onPointerDown(
	{
		entity: myEntity,
		opts: { button: InputAction.IA_PRIMARY, hoverText: 'Click' },
	},
	function () {
		console.log('clicked entity')
	}
)
```

Veja [**Registrar uma callback**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md) para mais informações.

## Hover Feedback

É importante deixar claro para os jogadores que uma Entity é interativa. Caso contrário, eles podem perder completamente a experiência que você criou. Não é uma boa experiência clicar em todos os objetos na esperança de que algum responda.

Quando você usa o [**Registrar uma callback**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md) método, dois tipos de feedback são exibidos sempre que o jogador passa o cursor sobre o objeto:

* A borda da Entity é destacada (apenas no cliente de desktop Decentraland 2.0). O destaque é verde se a Entity estiver perto o suficiente para clicar, vermelho se a Entity estiver longe demais.
* Uma dica de hover aparece perto do cursor com texto de UI, sinalizando o que acontecerá se ele clicar.

Ao usar o [**Baseado em System**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/system-based-events.md) método, você pode obter os mesmos resultados adicionando um `PointerEvents` component às Entities clicáveis.

Tanto o destaque da Entity quanto a dica de hover podem ser desativados por meio de propriedades nesses métodos e components.

Você também pode implementar [dicas personalizadas avançadas](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/system-based-events.md#advanced-custom-hints), por exemplo, você pode tocar um som, fazer a Entity mudar de cor, girar ou aumentar enquanto estiver sendo apontada, etc. Seja o que for que você fizer, certifique-se de que seja um sinal claro.

## Obstáculos

Os eventos de botão lançam raios que interagem apenas com a primeira Entity em seu caminho que esteja inscrita na collision layer de pointer events. Isso é verdade enquanto a Entity estiver mais perto do que seus limites de distância tanto do avatar quanto da câmera.

Para que uma Entity seja interceptada pelo raio de um evento de ponteiro, é preciso que:

* O model deve conter [collider meshes](/creator/content-creator-pt/modelacao-e-animacoes-3d/colliders.md).
* A `GLTFContainer` deve ser configurado para usar a [geometria visível com collision masks](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#colliders-on-3d-models).
* A Entity deve ter um [MeshCollider component](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md).

Se o collider de outra Entity estiver no caminho da Entity com a qual o jogador deseja interagir, o jogador não conseguirá clicar na Entity que está atrás, a menos que a Entity não tenha collider, ou esse collider esteja configurado para não responder à collision layer de pointer events.

```ts
// clickable entity
const clickableEntity = engine.addEntity()
MeshRenderer.setBox(clickableEntity)
MeshCollider.setBox(clickableEntity)
Transform.create(clickableEntity, { position: Vector3.create(8, 1, 8) })

pointerEventsSystem.onPointerDown(
	{
		entity: clickableEntity,
		opts: {
			button: InputAction.IA_POINTER,
			hoverText: 'Click',
		},
	},
	function () {
		console.log('clicked entity')
		const t = Transform.getMutable(clickableEntity)
		t.scale.y += 0.2
	}
)

// non-blocker for clicks
const nonBlocker = engine.addEntity()
MeshRenderer.setBox(nonBlocker)
MeshCollider.setBox(nonBlocker, ColliderLayer.CL_PHYSICS)
Transform.create(nonBlocker, { position: Vector3.create(10, 1, 8) })

// blocker for clicks
const blocker = engine.addEntity()
MeshRenderer.setBox(blocker)
MeshCollider.setBox(blocker, ColliderLayer.CL_POINTER)
Transform.create(blocker, { position: Vector3.create(8, 1, 10) })
```

{% hint style="warning" %}
**📔 Nota**: Para que uma Entity não apenas intercepte um evento de ponteiro, mas também retorne dados, a Entity também precisa ter um `PointerEvents` component. Os `pointerEventsSystem` helpers também cuidam desse requisito.
{% endhint %}

## Botões do ponteiro

Os seguintes inputs podem ser tratados por qualquer uma das abordagens para detectar eventos de input.

* `InputAction.IA_POINTER`: **botão esquerdo do mouse** em um computador, **botão de interação** no mobile.
* `InputAction.IA_PRIMARY`: **E** tecla em um computador, **Botão E** no mobile.
* `InputAction.IA_SECONDARY`: **F** tecla em um computador, **Botão F** no mobile.
* `InputAction.IA_ACTION_3`: **1** tecla em um computador, **botão 1** no mobile. *Não é facilmente acessível no mobile — não recomendado para interação mobile.*
* `InputAction.IA_ACTION_4`: **2** tecla em um computador, **botão 2** no mobile. *Não é facilmente acessível no mobile — não recomendado para interação mobile.*
* `InputAction.IA_ACTION_5`: **3** tecla em um computador, **botão 3** no mobile. *Não é facilmente acessível no mobile — não recomendado para interação mobile.*
* `InputAction.IA_ACTION_6`: **4** tecla em um computador, **botão 4** no mobile. *Não é facilmente acessível no mobile — não recomendado para interação mobile.*
* `InputAction.IA_JUMP`: **Space** tecla em um computador, **botão de pular** no mobile.
* `InputAction.IA_FORWARD`: **W** tecla em um computador.
* `InputAction.IA_LEFT`: **A** tecla em um computador.
* `InputAction.IA_RIGHT`: **D** tecla em um computador.
* `InputAction.IA_BACKWARD`: **S** tecla em um computador.
* `InputAction.IA_WALK`: **Control** tecla em um computador.
* `InputAction.IA_MODIFIER`: **Shift** tecla em um computador.

Cada `InputAction` é abstraído do input literal no teclado para que possa ser mapeado para diferentes inputs dependendo do dispositivo. Pela mesma razão, nem todos os botões do teclado podem ser rastreados para eventos de botão, apenas os botões usados para movimento e interação. Essa limitação intencional garante que o conteúdo seja compatível entre desktop, o [cliente mobile](/creator/content-creator-pt/scenes-sdk7/criar-para-mobile/building-for-mobile.md), e futuros dispositivos como controles VR e outros controles de jogo.

{% hint style="warning" %}
**📱 Mobile**: No [cliente mobile](/creator/content-creator-pt/scenes-sdk7/criar-para-mobile/building-for-mobile.md), todas as ações de input estão disponíveis, mas `IA_ACTION_3`–`IA_ACTION_6` (a `1`/`2`/`3`/`4` botões) ficam escondidos atrás de um menu secundário e não são facilmente acessíveis durante o gameplay. Ao projetar para mobile, prefira `IA_POINTER` (botão de interação), `IA_PRIMARY` (botão E), e `IA_SECONDARY` (botão F) para suas ações principais. Veja [Input no mobile](/creator/content-creator-pt/scenes-sdk7/criar-para-mobile/input-on-mobile.md).
{% endhint %}

## Tipos de eventos de ponteiro

Cada input pode produzir os seguintes tipos de eventos de ponteiro. Cada um dos seguintes é um valor no `PointerEventType` enum.

* `DOWN`: O jogador pressiona um botão específico enquanto o cursor está apontando para o collider da Entity.
* `UP`: O jogador solta um botão específico enquanto o cursor está apontando para o collider da Entity.
* `HOVER_ENTER`: O cursor do jogador começa a apontar para o collider da Entity.
* `HOVER_LEAVE`: O cursor do jogador para de apontar para o collider da Entity.
* `PROXIMITY_ENTER`: O jogador entra na faixa de proximidade da Entity, independentemente de onde esteja olhando.
* `PROXIMITY_LEAVE`: O jogador sai da faixa de proximidade da Entity.

Veja [**Proximity Events**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/proximity-events.md) para saber como usar interações baseadas em proximidade.

## Dados de uma ação de input

Todas as ações de input incluem dados sobre o evento, incluindo coisas como o botão que foi ativado e para onde o ponteiro estava apontando no momento.

As seguintes informações podem ser obtidas de qualquer evento de input:

* `analog`: Indicador para marcar se o evento é de um input analógico ou digital. Inputs digitais têm um valor de *1*, inputs analógicos (como um joystick) têm um valor de *0*.
* `button`: Qual id de botão foi pressionado. O número corresponde ao `InputAction` enum, que lista todos os botões disponíveis.
* `state`: Tipo de evento de ponteiro, do enum `PointerEventType`. *0* refere-se a `PointerEventType.PET_DOWN`, *1* a `PointerEventType.PET_UP`, *2* a `PointerEventType.PET_HOVER_ENTER`, *3* a `PointerEventType.PET_HOVER_LEAVE`
* `timestamp`: Um [carimbo de data e hora de Lamport](https://en.wikipedia.org/wiki/Lamport_timestamp) para identificar cada evento de botão.

  > Nota: Este timestamp não é numerado com base na hora atual. Pense nele como um contador que começa em 0 e é incrementado em 1 para cada evento.
* `hit`: Um objeto que contém os seguintes dados sobre o evento de hit:
  * `entityId`: Número de id da Entity que foi atingida pelo raio.
  * `meshName`: *String* com o nome interno do mesh específico no model 3D que foi atingido. Isso é útil quando um model 3D é composto por vários meshes.
  * `origin`: *Vector3* para a posição de onde o raio se origina (relativa à scene)
  * `position`: *Vector3* para a posição onde o raio intersectou a Entity atingida (relativa à scene)
  * `length`: Comprimento do raio desde a origem até a posição onde ocorreu o hit contra a Entity.
  * `normalHit`: *Quaternion* para o ângulo da normal do hit no espaço mundial.

Esses dados são acessados de maneiras diferentes dependendo da abordagem que você está usando para lidar com ações de input.

Usando a [**Registrar uma callback**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md) abordagem, o primeiro parâmetro passado para a função de callback contém toda essa estrutura de dados.

```ts
pointerEventsSystem.onPointerDown({ entity: myEntity }, function (cmd) {
	console.log(cmd.hit.entityId)
})
```

Usando a [**Baseado em System**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/system-based-events.md) abordagem, use `inputSystem.getInputCommand()` para buscar esses dados.

```ts
engine.addSystem(() => {
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)
	if (cmd) {
		console.log(cmd.hit.entityId)
	}
})
```

{% hint style="warning" %}
**📔 Nota**: Para que uma Entity não apenas intercepte um evento de ponteiro, mas também retorne dados, a Entity também precisa ter um `PointerEvents` component. Os `pointerEventsSystem` helpers também cuidam desse requisito.
{% endhint %}

Usando a [**Avançado**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/advanced-button-events.md) abordagem, o `PointerEventsResults` contém um array com um histórico recente de todos os eventos de ponteiro contra essa Entity.

```ts
engine.addSystem(() => {
	const pointerEvents = engine.getEntitiesWith(PointerEventsResult)
	for (const [entity] of pointerEvents) {
		const poninterEvents = PointerEventsResult.get(entity)

		if (poninterEvents.commands.length > 0) {
			console.log(poninterEvents.commands[0].hit.entityId)
		}
	}
})
```

## Bloquear ou desbloquear o cursor

{% hint style="info" %}
**💡 Nota**: `PointerLock` é um conceito do cliente de desktop (cursor do mouse bloqueado vs. desbloqueado). Isso não tem efeito no [app mobile](/creator/content-creator-pt/scenes-sdk7/criar-para-mobile/building-for-mobile.md), onde o input é baseado em toque.
{% endhint %}

Os jogadores no cliente de desktop do Decentraland podem alternar entre dois modos distintos de interação com o cursor:

* Cursor bloqueado: mover o mouse desloca a câmera e os eventos de clique ocorrem na mira no centro da tela
* Cursor desbloqueado: o cursor fica livre para se mover independentemente da câmera, e os jogadores podem clicar em qualquer lugar da tela para interagir com o espaço 3D ou com a UI

Esses modos de interação são ideais para diferentes tipos de mecânicas de jogo, e você pode querer fazer com que os jogadores adotem um ou outro dependendo do que melhor se encaixa na sua scene. Você também pode querer garantir momentaneamente que o cursor do jogador esteja desbloqueado para permitir que ele interaja com uma UI; isso é especialmente útil para novos jogadores que não estão familiarizados com como isso é controlado.

Para alterar o estado do cursor do jogador, use o `PointerLock` component na `engine.CameraEntity` entity.

```ts
import {PointerLock} from '@dcl/sdk/ecs'
    
PointerLock.create(engine.CameraEntity, {isPointerLocked: false})
```

Você também pode consultar o estado do cursor do jogador lendo o estado do `PointerLock` component.

```ts
import {PointerLock} from '@dcl/sdk/ecs'

PointerLock.create(engine.CameraEntity)

const isPointerLocked = PointerLock.get(engine.CameraEntity).isPointerLocked
```

Use a `.onChange` function para reagir a mudanças no estado do ponteiro. O exemplo a seguir garante que o cursor esteja sempre desbloqueado.

```ts
import {PointerLock} from '@dcl/sdk/ecs'

export function main() {

    PointerLock.create(engine.CameraEntity, {isPointerLocked: false});

    PointerLock.onChange(engine.CameraEntity, (pointerLock) => {
		    if (!pointerLock) return
		    if(pointerLock.isPointerLocked){
			    PointerLock.getMutable(engine.CameraEntity).isPointerLocked = false
		   }
	})
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
