> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/system-based-events.md).

# Eventos Baseados em System

Saiba como lidar com cliques de usuário na sua scene.

Se sua Scene tiver várias entities semelhantes que são ativadas usando a mesma lógica, você pode escrever um único system para iterar por todas elas e descrever esse comportamento apenas uma vez. Essa também é a opção de melhor desempenho e mais [orientada a dados](/creator/content-creator-pt/scenes-sdk7/arquitetura/data-oriented-programming.md) abordagem.

Você também pode usar um system para detectar [eventos globais de input](#global-input-events), para que a Scene reaja sempre que uma tecla for pressionada, sem considerar para onde o cursor do jogador está apontando.

Se tudo o que você quer fazer é clicar ou pressionar um botão em uma única entity para ativá-la, a maneira mais fácil é usar o [Registrar um callback](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md) abordagem.

Para definir uma lógica customizada mais específica, talvez você queira lidar com os dados brutos e usar o [Avançado](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/advanced-button-events.md) abordagem.

Para que uma entity seja interativa, ela deve ter um [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md). Veja [obstáculos](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#obstacles) para mais detalhes. Isso também se aplica aos eventos de clique por proximidade.

## Usando um system

Verifique eventos de botão executando uma das funções auxiliares no namespace input `inputSystem` a cada tick dentro de um [system](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md).

Por exemplo, o seguinte system usa a `inputSystem.isTriggered()` função para verificar se o pointer foi clicado. A cada tick, ele verifica se o botão foi pressionado. Se `inputSystem.isTriggered()` retorna *true*, o system executa alguma lógica customizada em resposta.

```ts
engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
		// Lógica em resposta ao pressionar o botão
	}
})
```

As seguintes funções auxiliares estão disponíveis no `inputSystem` namespace, e podem ser chamadas da mesma forma a cada tick:

* `inputSystem.isTriggered`: Retorna true se uma ação de input ocorreu desde o último tick.
* `inputSystem.isPressed`: Retorna true se um input estiver atualmente sendo pressionado. Retornará true a cada tick até o botão ser solto novamente.
* `inputSystem.getInputCommand`: Retorna um objeto com dados sobre a ação de input.

Veja as seções abaixo para mais detalhes sobre cada um.

Ao lidar com eventos de botão em uma entity, sempre forneça feedback ao jogador, para que ele saiba que uma entity pode ser interagida. Se você adicionar um `PointerEvents` component a uma entity, os jogadores verão uma dica ao passar o cursor sobre essa entity. Veja [Mostrar feedback](#show-feedback) para aprender como você pode adicionar dicas de hover em entities interativas.

### Eventos globais de input

Use `inputSystem.isTriggered` para detectar eventos de botão pressionado e solto em qualquer um dos inputs monitorados pelo SDK.

```ts
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)
	) {
		// Lógica em resposta ao pressionar o botão
	}
})
```

O exemplo acima verifica se o botão foi pressionado, independentemente de onde o pointer está ou de quais entities possam estar em seu caminho.

`inputSystem.isTriggered()` retorna *true* somente se o botão indicado tiver sido pressionado no tick atual do game loop. Se o botão não tiver sido pressionado, ou já estivesse pressionado no tick anterior, ele retorna *false*.

{% hint style="warning" %}
**📔 Observação**: O jogador precisa estar dentro dos limites da Scene para que o pointer event seja detectado. O cursor do jogador também precisa estar travado; botões pressionados com o cursor livre não são detectados.

Toda entity com a qual você quer interagir deve ter tanto um [`PointerEvents` component](#show-feedback) e uma [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md).
{% endhint %}

O `inputSystem.isTriggered` função recebe os seguintes argumentos obrigatórios:

* `InputAction`: Qual input escutar, como um valor do `InputAction` enum. Veja [Botões do Pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para as opções suportadas.
* `PointerEventType`: Qual tipo de event escutar, como um valor do `PointerEventType` enum. Veja [Tipos de eventos de ponteiro](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#types-of-pointer-events) para as opções suportadas.

### Ativar uma entity

Para detectar eventos de botão ao apontar para uma entity específica, passe um terceiro argumento opcional para `inputSystem.isTriggered` para especificar contra qual entity verificar.

```ts
// Dê à entity um component PointerEvents
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				showFeedback: false,
			},
		},
	],
})

// criar system
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_DOWN,
			myEntity
		)
	) {
		// Lógica em resposta ao pressionar o botão em myEntity
	}
})
```

O exemplo acima verifica a cada tick se uma única entity codificada manualmente foi pressionada com o botão pointer (botão esquerdo do mouse).

O `inputSystem.isTriggered` function recebe os seguintes argumentos:

* `InputAction`: Qual input escutar, como um valor do `InputAction` enum. Veja [Botões do Pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para as opções suportadas.
* `PointerEventType`: Qual tipo de event escutar, como um valor do `PointerEventType` enum. Veja [Tipos de eventos de ponteiro](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#types-of-pointer-events) para as opções suportadas.
* `Entity` *(opcional)*: Qual entity verificar para esses eventos. Se nenhum valor for fornecido, ele verificará pressionamentos globais do botão, independentemente de onde o cursor do jogador estava apontando.

Observe que, neste exemplo, também estamos adicionando um `PointerEvents` component à entity com a qual queremos interagir. Esta etapa é necessária; sem esse component a entity não poderá ser detectada por nenhuma das funções de `inputSystem`. veja [Mostrar feedback](#show-feedback) para mais detalhes sobre o `PointerEvents` component.

{% hint style="warning" %}
**📔 Observação**: e um [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md). Veja [obstáculos](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#obstacles) para mais detalhes.
{% endhint %}

Se houver várias entities com as quais o jogador possa interagir da mesma forma, considere usar `inputSystem.getInputCommand`. Este comando retorna informações sobre um comando global de clique, incluindo o ID da entity; você pode usar isso para executar uma única função capaz de lidar com todas elas.

```ts
engine.addSystem(() => {
	const result = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN
	)
	if (result) {
		if (result.hit?.entityId === myEntity) {
			// lidar com o clique
		}
	}
})
```

{% hint style="warning" %}
**📔 Observação**Toda entity com a qual você quer interagir deve ter tanto um [`PointerEvents` component](#show-feedback) e uma [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md).
{% endhint %}

Veja [Dados da input action](#data-from-input-action) para mais informações. Este método também fornece dados mais detalhados sobre o hit do pointer event.

### Botão de input solto

Você também pode verificar eventos de pointer up de maneira muito semelhante, usando `PointerEventType.PET_UP`.

```ts
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_UP,
			myEntity
		)
	) {
		// Lógica em resposta ao soltar o botão enquanto aponta para myEntity
	}
})
```

{% hint style="warning" %}
**📔 Observação**: Ao verificar eventos de pointer up em relação a uma entity específica, isso não leva em consideração para onde o cursor estava apontando quando o botão foi pressionado. Considera apenas para onde o cursor está apontando quando o botão é solto.

Lembre também que a entity deve ter tanto um [`PointerEvents` component](#show-feedback) e uma [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md).
{% endhint %}

### Verifique botões pressionados

Verifique se um botão está atualmente sendo pressionado usando `inputSystem.isPressed()` dentro de um system.

```ts
engine.addSystem(() => {
	if (inputSystem.isPressed(InputAction.IA_POINTER)) {
		// Lógica em resposta ao botão mantido pressionado
	}
})
```

`inputSystem.isPressed()` retorna *true* se o botão estiver atualmente sendo mantido pressionado, independentemente de quando foi pressionado e de para onde o cursor do jogador está apontando. Caso contrário, ele retorna *false*.

O `inputSystem.isPressed` função recebe um único argumento:

* `InputAction`: Qual input escutar, como um valor do `InputAction` enum. Veja [Botões do Pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para as opções suportadas.

### Lidar com várias entities

Se sua Scene tiver várias entities afetadas por pointer events da mesma forma, faz sentido escrever um system que itere por todas elas.

```ts
engine.addSystem(() => {
	const activatedEntites = engine.getEntitiesWith(PointerEvents)
	for (const [entity] of activatedEntites) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				entity
			)
		) {
			// Lógica em resposta à interação com uma entity
		}
	}
})
```

Este exemplo usa um [consulta de component](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md) para iterar por todas as entities com um `PointerEvents` component. Em seguida, verifica cada uma dessas entities com `inputSystem.isTriggered`, iterando por elas uma a uma. Se uma ação de input for detectada em qualquer uma dessas entities, ela executa lógica customizada.

Em vez de iterar por *todos os* as entities com um `PointerEvents` component em um único system, talvez você queira escrever systems diferentes para lidar com entities que devem se comportar de maneiras diferentes. A abordagem recomendada é marcar diferentes tipos de entities com specific [custom components](/creator/content-creator-pt/scenes-sdk7/arquitetura/custom-components.md), e iterar por elas em systems separados.

```ts
engine.addSystem(() => {
	const activatedDoors = engine.getEntitiesWith(IsDoor, PointerEvents)
	for (const [entity] of activatedDoors) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				entity
			)
		) {
			openDoor(entity)
		}
	}
})

engine.addSystem(() => {
	const pickedUpGems = engine.getEntitiesWith(IsGem, PointerEvents)
	for (const [entity] of pickedUpGems) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				entity
			)
		) {
			pickUp(entity)
		}
	}
})
```

Este exemplo tem um system que itera por todas as entities que têm um component customizado chamado `IsDoor` e outro que itera por todas as entities que têm um component customizado chamado `isGem`. Em ambos os systems, verifica cada entity correspondente para ver se elas foram ativadas com o botão pointer.

Essa forma de organizar o código da sua Scene é muito [orientada a dados](/creator/content-creator-pt/scenes-sdk7/arquitetura/data-oriented-programming.md) e deve resultar em um uso muito eficiente dos recursos de memória.

\## Vários botões em uma entity

Usando auxiliares como `pointerEventsSystem.onPointerDown`, cada entity fica limitada a ter um único tipo de event. Você não pode registrar dois eventos de botão diferentes. Você não tem essa limitação ao usar events baseados em system. Por exemplo, aqui está uma entity com a qual os jogadores podem interagir tanto pressionando E quanto F, cada um acionando funcionalidades diferentes.

```ts
    engine.addSystem(() => {
        if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
            // reagir a E
        }
        if (inputSystem.isTriggered(InputAction.IA_SECONDARY, PointerEventType.PET_DOWN, myEntity)) {
            // reagir a F
        }
    })
```

## Mostrar feedback

Para exibir dicas de UI ao apontar para uma entity, use as propriedades no `PointerEvents` component.

```ts
// criar entity
const myEntity = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
			},
		},
	],
})
```

Sempre que o cursor do jogador apontar para os colliders desta entity, a UI exibirá uma dica de hover para indicar que a entity pode ser interagida. Veja as seções abaixo para detalhes sobre o que você pode configurar.

{% hint style="warning" %}
**📔 Observação**: A `PointerEvents` component apenas lida com a exibição do feedback de hover. Para lidar com os próprios eventos de botão com lógica customizada, veja [Using-a-system](#check-for-events).
{% endhint %}

O `PointerEvents` component requer pelo menos uma definição de pointer event. Cada definição de pointer event pode ser configurada com o seguinte:

* `eventType`: Qual tipo de event escutar, como um valor do `PointerEventType` enum. Veja [Tipos de eventos de ponteiro](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#types-of-pointer-events) para as opções suportadas.
* `eventInfo`: Um objeto que pode conter os seguintes campos:
  * `button` (*obrigatório*): Qual input escutar, como um valor do `InputAction` enum. Veja [Botões do Pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para as opções suportadas.
  * `hoverText` *(opcional)*: Qual string exibir na dica de feedback de hover. "Interact" por padrão.
  * `showFeedback` *(opcional)*: Se false, oculta tanto a dica de hover quanto o realce da borda para esta Entity. *true* por padrão.
  * `showHighlight` *(opcional)*: Se true, os players verão o realce da borda ao passar o cursor sobre a Entity. *true* por padrão. Esse valor só é considerado se `showFeedback` é *true*.
  * `maxDistance` *(opcional)*: A que distância o avatar do jogador **avatar** pode estar da entity e ainda interagir com ela, em metros. O padrão é *10 metros*. Veja [Distância máxima](#max-distance).
  * `maxCameraDistance` *(opcional)*: A que distância o avatar do jogador **câmera ativa** pode estar da entity e ainda interagir com ela, em metros. Não definido por padrão. Veja [Distância máxima](#max-distance).
  * `prioridade` *(opcional)*: Qual entity vence quando várias se sobrepõem. Valores mais altos têm precedência. *0* por padrão.

Um único `PointerEvents` component pode conter múltiplas definições de pointer event, que podem detectar eventos diferentes para botões diferentes. Cada entity pode ter apenas *um* `PointerEvents` component, mas este component pode incluir vários objects em seu `pointerEvents` array, um para cada event ao qual responder.

```ts
PointerEvents.create(NPCEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Cumprimentar',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'Estrangular',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'Parar de estrangular',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_SECONDARY,
				hoverText: 'Dar gema',
			},
		},
	],
})
```

Os jogadores verão vários rótulos, um para cada pointer event, exibidos radialmente ao redor do cursor.

O exemplo abaixo combina o uso de `PointerEvents` para mostrar dicas de hover, juntamente com um system que realmente lida com a ação do jogador com lógica customizada.

```ts
// criar entity
const myEntity = engine.addEntity()

// dar feedback de hover à entity
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Abrir',
			},
		},
	],
})

// lidar com eventos de clique na entity
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_DOWN,
			myEntity
		)
	) {
		// Lógica customizada em resposta a uma ação de input
	}
})
```

### Feedback ao passar o mouse

Quando um jogador passa o cursor sobre um item com um `PointerEvents` component, ele vê:

* Um realce de borda na Entity
* Uma dica de hover perto do cursor com um ícone para o botão que precisam pressionar e uma string que diz "Interact".

Esses elementos podem ser ativados/desativados e personalizados.

O feedback de hover na UI exibe um ícone diferente dependendo de qual input você selecionar no `button` campo. No PC, ele exibe um ícone com um `E` para `InputAction.IA_PRIMARY`, um `F` para `InputAction.IA_SECONDARY`, e um mouse para `InputAction.IA_POINTER`.

Altere a string alterando o `hoverText` valor. Mantenha essa string curta, para que seja rápida de ler e não seja muito intrusiva na tela.

```ts
// criar entity
const chest = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Abrir',
			},
		},
	],
})
```

No exemplo acima, o pointer event inclui um valor para `hoverText`. Este campo define a string a ser exibida na UI enquanto o jogador aponta para a entity. Por padrão, essa string escreve *Interact*.

{% hint style="info" %}
**💡 Dica**: A `hoverText` string deve descrever a ação que acontece ao interagir. Por exemplo `Open`, `Ativar`, `Pegar`, `Selecione`. Essas strings devem ser o mais curtas possível, para evitar tirar atenção demais do jogador.
{% endhint %}

Se uma entity tiver vários pointer events, as dicas de hover de cada um deles serão exibidas radialmente ao redor do cursor.

O `hoverText` de um `.UP` pointer event só é exibido enquanto o jogador já estiver mantendo a tecla correspondente pressionada e apontando para a entity.

Se uma entidade tiver tanto um `DOWN` pointer event e um `UP` A dica para o `DOWN` ação é exibida enquanto o botão não está sendo pressionado. A dica muda para a do `UP` event somente quando o botão é pressionado e permanece pressionado.

```ts
// criar entity
const entity = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(entity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Arrastar',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Soltar',
			},
		},
	],
})
```

Para ocultar a dica de hover, mas manter o realce da borda, defina o valor do `hoverText` para "".

```ts
// criar entity
const chest = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '',
			},
		},
	],
})
```

Para ocultar o realce da borda, mas manter a dica de hover, defina `showHighlight` como *false*.

```ts
// criar entity
const chest = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Open door',
				showHighlight: false,
			},
		},
	],
})
```

Para ocultar tanto a dica de hover quanto o realce da borda, defina `showFeedback` como *false*. Ao fazer isso, o cursor não mostra nenhum ícone, texto ou destaque de borda. Você também poderia simplesmente remover o `PointerEvents` component da entity.

```ts
// criar entity
const chest = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				showFeedback: false,
			},
		},
	],
})
```

### Distância máxima

Algumas entities podem ser intencionalmente interativas apenas a curta distância. Se um jogador estiver longe demais de uma entity, a dica de hover não será exibida ao lado do cursor.

Por padrão, entities só são clicáveis quando o cursor do jogador **avatar** está dentro de *10 metros* da entity. Você pode alterar esse alcance definindo a `maxDistance` propriedade de um pointer event.

```ts
// criar entity
const myEntity = engine.addEntity()

// dê à entity um component PointerEvents
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 6,
			},
		},
	],
})

// implementar um system para lidar com o pointer event
engine.addSystem(() => {
	// obter dados sobre o pointer event
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)

	// verificar se o clique estava perto o suficiente
	if (cmd && cmd.hit && cmd.hit.length < 6) {
		// faça algo
	}
})
```

O exemplo acima define a distância máxima para dicas de hover como *6 metros*. Certifique-se de que a lógica para lidar com as ações de input também siga as mesmas regras. Veja [Dados da input action](#data-from-input-action) como obter a distância de uma ação de input.

`maxDistance` é medida a partir do avatar do jogador **avatar**, portanto se comporta da mesma forma em primeira e terceira pessoa.

Para limitar a interação pela distância em que o avatar **câmera ativa** está, use `maxCameraDistance`. Definir ambos significa que passar em qualquer uma das verificações é suficiente. Veja [Limites de distância](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md#distance-limits) para o conjunto completo de regras.

{% hint style="warning" %}
**📔 Observação**: `maxPlayerDistance` é um alias obsoleto de `maxDistance`. Ambos medem a distância a partir do avatar, então use `maxDistance` em novas Scenes.
{% endhint %}

## Dicas customizadas avançadas

O `PointerEvents` component adiciona facilmente dicas de UI quando o cursor do jogador começa a passar o hover sobre uma entity. Em geral, é bom que as dicas se comportem de forma consistente com o que os jogadores estão acostumados a ver em outras Scenes do Decentraland. No entanto, em alguns casos você pode querer sinalizar que algo é interativo de uma forma customizada. Por exemplo, você poderia tocar um som sutil quando o jogador começa a passar o hover sobre a entity. Você também poderia mostrar um destaque brilhante ao redor da entity enquanto estiver em hover e escondê-lo quando não houver mais hover. Isso também poderia ser usado para mecânicas específicas de gameplay.

Use o `inputSystem.isTriggered()` função juntamente com os `PointerEventType.PET_HOVER_ENTER` e `PointerEventType.PET_HOVER_LEAVE` events para executar comportamentos customizados sempre que o cursor do jogador começar a apontar para o collider da entity e sempre que o cursor parar de apontar para ele.

O exemplo abaixo aumenta entities para um tamanho de *1.5* quando o cursor começa a apontar para o collider delas, e as retorna para um tamanho de *1* quando o cursor se afasta delas.

```ts
engine.addSystem(() => {
	const meshEntities = engine.getEntitiesWith(MeshRenderer)
	for (const [entity] of meshEntities) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_HOVER_ENTER,
				entity
			)
		) {
			Transform.getMutable(entity).scale = Vector3.create(1.5, 1.5, 1.5)
		}

		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_HOVER_LEAVE,
				entity
			)
		) {
			Transform.getMutable(entity).scale = Vector3.create(1, 1, 1)
		}
	}
})
```

{% hint style="warning" %}
**📔 Observação**Toda entity com a qual você quer interagir deve ter tanto um [`PointerEvents` component](#show-feedback) e uma [collider](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/colliders.md).
{% endhint %}

## Eventos de proximidade

Verifique pressionamentos de botão por proximidade independentemente de para onde o cursor esteja apontando usando `PET_DOWN` em uma entity que usa `InteractionType.PROXIMITY`. Defina o `interactionType` campo na definição do pointer event, junto a `eventInfo`, para marcar o event como baseado em proximidade.

Veja [**Proximity Events**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/proximity-events.md) para mais detalhes, incluindo as funções auxiliares disponíveis.

```ts
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'Pressione E',
				maxDistance: 5
			},
			interactionType: InteractionType.PROXIMITY,
		},
	],
})

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
		console.log('O jogador pressionou o botão perto da entity')
	}
})
```

Com auxiliares como `pointerEventsSystem.onProximityDown`, uma entity pode ter um handler de cursor e um handler de proximidade ao mesmo tempo, e ambos os callbacks são executados. O que ela não pode fazer é registrar dois botões diferentes para o mesmo handler. Eventos baseados em system não têm nenhuma dessas limitações: você define uma entrada por comportamento. Por exemplo, aqui está uma entity com a qual se pode interagir tanto apontando com o cursor e pressionando E quanto caminhando até perto dela e pressionando E sem apontar para ela com o cursor.

```ts
	PointerEvents.create(myEntity, {
        pointerEvents: [
            {
                eventType: PointerEventType.PET_DOWN,
                eventInfo: {
                    button: InputAction.IA_POINTER,
                    hoverText: 'Click',
                    maxDistance: 15,
                },
                interactionType: InteractionType.CURSOR,
            },
            {
                eventType: PointerEventType.PET_DOWN,
                eventInfo: {
                    button: InputAction.IA_PRIMARY,
                    hoverText: 'Pressione E',
                    maxDistance: 15,
                },
                interactionType: InteractionType.PROXIMITY,
            },
        ],
    })
    
    engine.addSystem(() => {
        if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, myEntity)) {
            console.log('O jogador clicou na entity')
        }
        if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
            console.log('O jogador pressionou o botão perto da entity')
        }
    })
```

Você também pode usar `inputSystem.isTriggered()` com o `PET_PROXIMITY_ENTER` e `PET_PROXIMITY_LEAVE` tipos de event para reagir quando um jogador entra ou sai do alcance de proximidade de uma entity. Isso é útil para exibir feedback extra para entities ativadas por proximidade, por exemplo tocar um som ou uma animação.

Para isso funcionar, a entity deve ter um `PointerEvents` component com o tipo de proximity event correspondente definido.

```ts
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_PROXIMITY_ENTER,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 5,
			},
		},
		{
			eventType: PointerEventType.PET_PROXIMITY_LEAVE,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 5,
				showFeedback: false,
			},
		},
	],
})

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_ENTER, myEntity)) {
		console.log('O jogador entrou na proximidade')
	}
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_LEAVE, myEntity)) {
		console.log('O jogador saiu da proximidade')
	}
})
```

## Dados da input action

Obtenha dados de uma input action, como o botão que foi pressionado, a Entity que foi atingida, a direção e o comprimento do ray, etc. Veja ([Ver documentação](https://github.com/decentraland/docs/tree/main/README.md)) para uma descrição de todos os dados disponíveis.

Para obter esses dados, use `inputSystem.getInputCommand`. Esta função retorna a estrutura de dados completa com dados sobre o input event.

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

Se não houve nenhuma ação de input que corresponda à consulta, então `inputSystem.getInputCommand` retorna *null*. Certifique-se de lidar com esse cenário na sua lógica.

### Distância máxima de clique

Para impor uma distância máxima, de modo que uma entity só possa ser clicada a curta distância, obtenha `hit.length` propriedade dos dados do event.

```ts
// implementar um system para lidar com o pointer event
engine.addSystem(() => {
	// obter dados sobre o pointer event
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)

	// verificar se o clique estava perto o suficiente
	if (cmd && cmd.hit && cmd.hit.length < 6) {
		// faça algo
	}
})
```

{% hint style="warning" %}
**📔 Observação**: Se você ignorar quaisquer events que estejam longe, certifique-se de definir o `maxDistance` parâmetro no `PointerEvents` component para se comportar de forma consistente.
{% endhint %}

### Meshes diferentes dentro de um modelo

Frequentemente, *.glTF* modelos 3D são compostos por vários meshes, cada um com um nome interno individual. Todos os button events incluem a informação de qual mesh específico foi clicado, então você pode usar essa informação para acionar comportamentos de clique diferentes em cada caso.

Para ver como os meshes dentro do modelo são nomeados, você deve abrir o modelo 3D com uma ferramenta de edição, como [Blender](https://www.blender.org/) por exemplo.

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c0c8238fe31b8eb541ccb25d29459670a994f03e%2Fmesh-names%20\(1\).png?alt=media)

{% hint style="info" %}
**💡 Dica**: Você também pode descobrir o nome do mesh clicado registrando-o e lendo-o no console.
{% endhint %}

Você acessa a `meshName` propriedade como parte do `impacto` objeto, que é retornado pelo evento de clique.

No exemplo abaixo temos um modelo de casa que inclui um mesh chamado `firePlace`. Queremos ligar a lareira apenas quando o mesh correspondente for clicado.

```ts
engine.addSystem(() => {
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)
	if (cmd && cmd.hit?.meshName === 'firePlace') {
		// acender o fogo
	}
})
```

{% hint style="warning" %}
**📔 Observação**: Isso se aplica apenas a events baseados em pointer, não a events baseados em proximity, pois nesse caso todos os meshes do modelo poderiam estar na proximidade do jogador ao mesmo tempo.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
