# Eventos baseados em Systems

Se a sua Scene tiver várias entities semelhantes que são todas ativadas usando a mesma lógica, você pode escrever um único system para iterar sobre todas elas e descrever esse comportamento apenas uma vez. Esta também é a abordagem mais performática 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 player está apontando.

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

Para definir uma custom logic mais específica, talvez você queira lidar com os dados brutos e usar o [Advanced](/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/essenciais-de-conteudo-3d/colliders.md). Veja [obstacles](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#obstacles) para mais detalhes. Isso também se aplica a eventos de clique por proximidade.

## Usando um system

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

Por exemplo, o system a seguir usa a `inputSystem.isTriggered()` function para verificar se o pointer foi clicado. Em cada tick, ele verifica se o botão foi pressionado. Se `inputSystem.isTriggered()` retorna *true*, o system executa uma custom logic em resposta.

```ts
engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
		// Logic em resposta à pressão do botão
	}
})
```

As seguintes funções auxiliares estão disponíveis no namespace `inputSystem` e podem ser chamadas de forma semelhante em cada tick:

* `inputSystem.isTriggered`: Retorna true se uma input action ocorreu desde o último tick.
* `inputSystem.isPressed`: Retorna true se uma input estiver atualmente sendo pressionada. Ela retornará true em cada tick até que o botão seja solto novamente.
* `inputSystem.getInputCommand`: Retorna um objeto com dados sobre a input action.

Consulte as seções abaixo para mais detalhes sobre cada uma.

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

### Eventos globais de input

Use `inputSystem.isTriggered` para detectar eventos de botão pressionado e botão solto em qualquer uma das inputs monitoradas pelo SDK.

```ts
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)
	) {
		// Logic em resposta à pressão do botão
	}
})
```

O exemplo acima verifica se o botão foi pressionado, independentemente de onde o pointer esteja 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 foi pressionado, ou já estava pressionado no tick anterior, ele retorna *false*.

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

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

O `inputSystem.isTriggered` function aceita os seguintes argumentos obrigatórios:

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

### Ativar uma entity

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

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

// create system
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_DOWN,
			myEntity
		)
	) {
		// Logic em resposta à pressão do botão em myEntity
	}
})
```

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

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

* `InputAction`: Qual input ouvir, como um valor de `InputAction` . Veja [Pointer buttons](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para opções suportadas.
* `PointerEventType`: Que tipo de evento ouvir, como um valor de `PointerEventType` . Veja [Tipos de eventos de pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#types-of-pointer-events) para opções suportadas.
* `Entity` *(opcional)*: Qual entity verificar para esses eventos. Se nenhum valor for fornecido, ele verificará pressões globais do botão, independentemente de onde o cursor do player estivesse 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 [Show Feedback](#show-feedback) para mais detalhes sobre o `PointerEvents` component.

{% hint style="warning" %}
**📔 Nota**: e um [collider](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md). Veja [obstacles](/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 player possa interagir da mesma maneira, considere usar `inputSystem.getInputCommand`. Este command retorna informações sobre um command de clique global, incluindo o ID da entity; você pode usar isso para executar uma única function que possa lidar com todas elas.

```ts
engine.addSystem(() => {
	const result = inputSystem.getInputCommand(
		InputAction.IA_LEFT,
		PointerEventType.PET_DOWN
	)
	if (result) {
		if (result.hit.entityId === myEntity) {
			// handle click
		}
	}
})
```

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

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

### Botão solto do input

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

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

{% hint style="warning" %}
**📔 Nota**: Ao verificar eventos de pointer solto 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. Ele considera apenas para onde o cursor está apontando no momento em que o botão é solto.

Também tenha em mente que a entity deve ter tanto um [`PointerEvents` component](#show-feedback) e um [collider](/creator/content-creator-pt/scenes-sdk7/essenciais-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)) {
		// Logic em resposta ao botão sendo mantido pressionado
	}
})
```

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

O `inputSystem.isPressed` function aceita um único argumento:

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

### Lidar com várias entities

Se sua scene tiver várias entities afetadas por eventos de pointer da mesma forma, faz sentido escrever um system que itere sobre 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
			)
		) {
			// Logic em resposta à interação com uma entity
		}
	}
})
```

Este exemplo usa um [consulta de componentes](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md) para iterar sobre todas as entities com um `PointerEvents` component. Em seguida, ele verifica cada uma dessas entities com `inputSystem.isTriggered`, iterando sobre elas uma por uma. Se uma input action for detectada em qualquer uma dessas entities, ele executa a custom logic.

Em vez de iterar sobre *todos os* as entities com um `PointerEvents` component em um único system, você pode querer escrever systems diferentes para lidar com entities que devem se comportar de maneiras diferentes. A abordagem recomendada é marcar diferentes tipos de entities com [custom components](/creator/content-creator-pt/scenes-sdk7/arquitetura/custom-components.md), e iterar sobre 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 sobre todas as entities que têm um custom component chamado `IsDoor` e outro que itera sobre todas as entities que têm um custom component chamado `isGem`. Em ambos os systems, ele verifica cada entity correspondente para ver se elas foram ativadas com o botão do 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 helpers como `pointerEventsSystem.onPointerDown`, cada entity fica limitada a ter um único tipo de evento. Você não pode registrar dois eventos de botão diferentes. Você não tem essa limitação ao usar eventos baseados em system. Por exemplo, aqui está uma entity com a qual os players podem interagir tanto pressionando E quanto F, cada um disparando 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
        }
    })
```

## Show feedback

Para exibir hints de UI enquanto aponta para uma entity, use as propriedades no `PointerEvents` component.

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

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

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

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

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

* `eventType`: Que tipo de evento ouvir, como um valor de `PointerEventType` . Veja [Tipos de eventos de pointer](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#types-of-pointer-events) para opções suportadas.
* `eventInfo`: Um objeto que pode conter os seguintes campos:
  * `button` (*obrigatório*): Qual input ouvir, como um valor de `InputAction` . Veja [Pointer buttons](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#pointer-buttons) para opções suportadas.
  * `hoverText` *(opcional)*: Qual string exibir na dica de hover feedback. "Interact" por padrão.
  * `hideFeedback` *(opcional)*: Se true, oculta tanto a dica de hover quanto o destaque de borda para esta entidade. *false* por padrão.
  * `showHighlight` *(opcional)*: Se true, os jogadores verão o destaque de borda ao passar o cursor sobre a entidade. *true* por padrão. Este valor só é considerado se `hideFeedback` for *false*.
  * `maxDistance` *(opcional)*: Mostra feedback apenas quando o player estiver mais perto do que uma certa distância da entity. O padrão é *10 metros*.

Um único `PointerEvents` component pode conter várias definições de eventos de pointer, que podem detectar eventos diferentes para botões diferentes. Cada entity pode ter apenas um *um* `PointerEvents` component, mas esse component pode incluir vários objetos em seu `pointerEvents` array, um para cada evento a ser tratado.

```ts
PointerEvents.create(NPCEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Greet',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'Choke',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'Stop Choke',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_SECONDARY,
				hoverText: 'Give gem',
			},
		},
	],
})
```

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

O exemplo abaixo combina o uso de `PointerEvents` para mostrar hover hints, junto com um system que realmente trata a ação do player com custom logic.

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

// give the entity hover feedback
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Open',
			},
		},
	],
})

// handle click events on the entity
engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, myEntity)) {
		// Custom logic em resposta a uma input action
	}
})
```

### Feedback de Hover

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

* Um destaque de borda na entidade
* Uma dica de hover próxima ao cursor com um ícone para o botão que eles precisam pressionar e uma string que diz "Interact".

Esses elementos podem ser alternados e personalizados.

O hover feedback na UI exibe um ícone diferente dependendo do input selecionado no `button` field. 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 fique muito intrusiva na tela.

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

// give entity a PointerEvents component
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Open',
			},
		},
	],
})
```

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

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

Se uma entity tiver vários eventos de pointer, os hover hints de cada um deles são exibidos radialmente ao redor do cursor.

O `hoverText` de um `.UP` evento de pointer é exibido apenas enquanto o player já estiver mantendo pressionada a tecla correspondente e apontando para a entity.

Se uma entity tiver tanto um `DOWN` evento de pointer e um evento `UP` de pointer, a hint da ação `DOWN` é mostrada enquanto o botão não está sendo pressionado. A hint muda para a do `UP` evento somente quando o botão é pressionado e permanece pressionado.

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

// give entity a PointerEvents component
PointerEvents.create(entity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Drag',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: 'Drop',
			},
		},
	],
})
```

Para ocultar a dica de hover, mas manter o destaque de borda, defina o valor de `hoverText` como "".

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

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

Para ocultar o destaque de borda, mas manter a dica de hover, defina `showHighlight` // desenhar UI *false*.

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

// give entity a PointerEvents component
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 destaque de borda, defina o `hideFeedback` para um true. Ao fazer isso, o cursor não mostra nenhum ícone, texto ou destaque de borda. Você também pode simplesmente remover o `PointerEvents` component da entity.

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

// give entity a PointerEvents component
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hideFeedback: true,
			},
		},
	],
})
```

### Distância máxima

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

Por padrão, as entities só podem ser clicadas quando o player está a curta distância da entity, com uma distância máxima de *10 metros*. Você pode alterar a distância máxima definindo a `maxDistance` property de um evento de pointer.

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

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

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

	// verificar se o clique foi suficientemente próximo
	if (cmd.hit.length < 6) {
		// fazer algo
	}
})
```

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

{% hint style="warning" %}
**📔 Nota**: A `maxDistance` é medido em metros a partir da câmera do player. Tenha em mente que, em terceira pessoa, a câmera fica um pouco mais distante, então certifique-se de que a distância definida funcione bem em ambos os modos.
{% endhint %}

## Hints customizados avançados

O `PointerEvents` component adiciona facilmente hints de UI quando o cursor do player começa a passar sobre uma entity. Em geral, é algo bom que os hints se comportem de forma consistente com o que os players estão acostumados a ver em outras scenes de 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 player começar a passar o cursor sobre a entity. Você também poderia mostrar um destaque brilhante ao redor da entity enquanto estiver em hover e ocultá-lo quando não estiver mais em hover. Isso também pode ser usado para mecânicas de gameplay específicas.

Use o `inputSystem.isTriggered()` function junto com os `PointerEventType.PET_HOVER_ENTER` e `PointerEventType.PET_HOVER_LEAVE` events para executar comportamentos customizados sempre que o cursor do player 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 redefine para um tamanho de *1* quando o cursor sai 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" %}
**📔 Nota**: Toda entity com a qual você deseja interagir deve ter tanto um [`PointerEvents` component](#show-feedback) e um [collider](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md).
{% endhint %}

## Eventos de proximidade

Verifique pressões de botão por proximidade independentemente de onde o cursor esteja apontando usando `PET_DOWN` em uma entity que usa `InteractionType.PROXIMITY`. Defina o `interactionType` campo em `eventInfo` para marcar o evento como baseado em proximidade.

Consulte [**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: 'Press E',
				maxPlayerDistance: 5
			},
			interactionType: InteractionType.PROXIMITY,
		},
	],
})

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
		console.log('Player pressed button near entity')
	}
})
```

Usando helpers como `pointerEventsSystem.onProximityDown`, cada entity fica limitada a ter um único tipo de evento. Você não pode registrar dois eventos de botão diferentes, ou até mesmo uma combinação de eventos de proximidade e pointer usando o mesmo botão. Você não tem essa limitação ao usar eventos baseados em system. Por exemplo, aqui está uma entity com a qual é possível interagir tanto apontando um cursor e pressionando E, quanto andando 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',
                    maxPlayerDistance: 15,
                },
                interactionType: InteractionType.CURSOR,
            },
            {
                eventType: PointerEventType.PET_DOWN,
                eventInfo: {
                    button: InputAction.IA_PRIMARY,
                    hoverText: 'Press E',
                    maxPlayerDistance: 15,
                },
                interactionType: InteractionType.PROXIMITY,
            },
        ],
    })
    
    engine.addSystem(() => {
        if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, myEntity)) {
            console.log('Player clicked at entity')
        }
        if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
            console.log('Player pressed button near entity')
        }
    })
```

Você também pode usar `inputSystem.isTriggered()` com o `PET_PROXIMITY_ENTER` e `PET_PROXIMITY_LEAVE` event types para reagir quando um player entra ou sai da faixa 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 correspondente tipo de evento de proximidade definido.

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

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_ENTER, myEntity)) {
		console.log('Player entered proximity')
	}
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_LEAVE, myEntity)) {
		console.log('Player left proximity')
	}
})
```

## Dados da ação de input

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

Para buscar esses dados, use `inputSystem.getInputCommand`. Esta function retorna a estrutura de dados completa com dados sobre o evento de input.

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

Se não houver nenhuma input action que corresponda à consulta, então `inputSystem.getInputCommand` retorna undefined. Certifique-se de tratar esse cenário na sua lógica.

### Distância máxima do clique

Para impor uma distância máxima, de modo que uma entity só possa ser clicada em curta distância, busque `hit.length` property dos dados do evento.

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

	// verificar se o clique foi suficientemente próximo
	if (cmd && cmd.hit.length < 6) {
		// fazer algo
	}
})
```

{% hint style="warning" %}
**📔 Nota**: Se você ignorar quaisquer eventos que estejam distantes, certifique-se de definir o `maxDistance` parameter no `PointerEvents` component para se comportar de forma consistente.
{% endhint %}

### Diferentes meshes dentro de um model

Muitas vezes, *.glTF* models 3D são compostos por vários meshes, cada um com um nome interno individual. Todos os eventos de botão incluem a informação de qual mesh específica foi clicada, então você pode usar essa informação para acionar diferentes comportamentos de clique em cada caso.

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

![](/files/7b17d133c3b69f2b2473370a856bd85548c947aa)

{% 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` property como parte do `hit` object, que é retornado pelo evento de clique.

No exemplo abaixo temos um model de casa que inclui um mesh chamado `firePlace`. Queremos ligar a lareira somente quando a mesh correspondente for clicada.

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

{% hint style="warning" %}
**📔 Nota**: Isso se aplica apenas a eventos baseados em pointer, e não a eventos baseados em proximidade, já que nesse caso todas as meshes do model poderiam estar próximas do player ao mesmo tempo.
{% endhint %}


---

# 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/system-based-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.
