> 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/mouse-movement.md).

# Movimento do Mouse

Reaja ao movimento do mouse do player em tempo real, para conduzir gestos de drag, girar objects ou controlar cameras personalizadas.

A sua cena pode ler o movimento bruto do mouse do jogador em cada frame e usá-lo para conduzir interações em tempo real: gestos de arrastar e deslizar, girando ou movendo objetos enquanto o jogador os arrasta, ou controlando uma câmera personalizada como em um jogo de tiro em primeira pessoa.

Para fazer isso, leia a `screenDelta` propriedade do `PrimaryPointerInfo` componente em `engine.RootEntity`. Esta propriedade é uma `Vector2` que informa quantos pixels o mouse se moveu desde o último frame. Valores positivos `x` significam que o mouse se moveu para a direita, valores positivos `y` significam que ele se moveu para cima, correspondendo à origem da tela no canto inferior esquerdo. Em frames em que o mouse não se move, ambos os valores são 0.

```ts
import { engine, PrimaryPointerInfo } from '@dcl/sdk/ecs'

engine.addSystem(() => {
	const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
	if (!delta) return
	console.log(`mouse moved: ${delta.x}, ${delta.y}`)
})
```

Como `screenDelta` contém apenas o movimento de um único frame, leia-o sempre dentro de um [system](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md), para que nenhum movimento passe despercebido entre os frames.

{% hint style="warning" %}
**📔 Nota**: Evite referir-se ao `engine.RootEntity` na carga inicial da cena, porque isso pode resultar em erros se as entities ainda não estiverem inicializadas. Para evitar esse problema, sempre se refira à entity dentro de um system. Ela sempre estará disponível, porque a primeira execução do system ocorre quando a cena já está devidamente inicializada.
{% endhint %}

{% hint style="warning" %}
**📔 Nota**: O que é descrito neste documento é relevante apenas para jogadores no desktop. No [aplicativo móvel](/creator/content-creator-pt/criar-para-dispositivos-moveis/mobile-client/overview.md), a entrada é baseada em toque e não há cursor livre, então `screenDelta` sempre retorna 0. Veja [Entrada em dispositivos móveis](/creator/content-creator-pt/criar-para-dispositivos-moveis/desenvolver/input-on-mobile.md) para ver como a entrada funciona em dispositivos de toque, e [Detectar plataforma](/creator/content-creator-pt/criar-para-dispositivos-moveis/desenvolver/detect-platform.md) para oferecer controles alternativos aos jogadores no mobile.
{% endhint %}

## O movimento do mouse enquanto o cursor está bloqueado

`screenDelta` se comporta de forma diferente das outras propriedades de `PrimaryPointerInfo` quando o cursor está [bloqueado](/creator/content-creator-pt/scenes-sdk7/interatividade/button-events/click-events.md#lock-or-unlock-the-cursor): `screenCoordinates` fica fixado no centro da tela e `worldRayDirection` sempre informa o raio no centro da tela, mas `screenDelta` continua reportando o movimento bruto do mouse em cada frame. Isso o torna a única maneira de ler o movimento do mouse enquanto o cursor está bloqueado, o que é exatamente o que você precisa para controles personalizados de câmera ou mira.

## Arraste para girar um objeto

O exemplo a seguir permite ao jogador girar um cubo arrastando o mouse lateralmente enquanto mantém o botão do ponteiro pressionado:

```ts
import {
	engine,
	InputAction,
	inputSystem,
	MeshCollider,
	MeshRenderer,
	PrimaryPointerInfo,
	Transform,
} from '@dcl/sdk/ecs'
import { Quaternion, Vector3 } from '@dcl/sdk/math'

const DRAG_SENSITIVITY = 0.5

export function main() {
	const cube = engine.addEntity()
	Transform.create(cube, { position: Vector3.create(8, 1, 8) })
	MeshRenderer.setBox(cube)
	MeshCollider.setBox(cube)

	engine.addSystem(() => {
		// gire apenas enquanto o botão do ponteiro estiver pressionado
		if (!inputSystem.isPressed(InputAction.IA_POINTER)) return

		const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
		if (!delta || delta.x === 0) return

		const transform = Transform.getMutable(cube)
		transform.rotation = Quaternion.multiply(
			transform.rotation,
			Quaternion.fromEulerDegrees(0, delta.x * DRAG_SENSITIVITY, 0)
		)
	})
}
```

O mesmo padrão funciona para qualquer interação de arrastar: deslize uma entity ao longo de um trilho usando `delta.x` como deslocamento, avance ou retroceda em uma animação, ou detecte um swipe rápido verificando valores grandes de delta.

## Controles de câmera em mouselook

Como `screenDelta` continua funcionando enquanto o cursor está bloqueado, você pode usá-lo para criar controles de mouselook para uma [virtual camera](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/camera.md#using-virtual-cameras). Para fazer isso, acumule o movimento do mouse em ângulos de yaw e pitch e depois aplique-os à rotação da câmera em cada frame.

No exemplo a seguir, o jogador clica em uma caixa para alternar para uma virtual camera que pode controlar com o mouse e pressiona o botão secundário (*F* ou clique com o botão direito) para voltar à câmera padrão. Enquanto a virtual camera está ativa, a cena também bloqueia o cursor e congela o avatar com um [input modifier](/creator/content-creator-pt/scenes-sdk7/interatividade/avatars/locomotion.md#freeze-the-player), para que o jogador não ande por aí às cegas enquanto controla a câmera.

```ts
import {
	engine,
	Entity,
	InputAction,
	InputModifier,
	inputSystem,
	MainCamera,
	MeshCollider,
	MeshRenderer,
	PointerEventType,
	pointerEventsSystem,
	PointerLock,
	PrimaryPointerInfo,
	Transform,
	VirtualCamera,
} from '@dcl/sdk/ecs'
import { Quaternion, Vector3 } from '@dcl/sdk/math'

// graus de rotação da câmera por pixel de movimento do mouse
const SENSITIVITY = 0.15

let cameraEntity: Entity
let cameraActive = false
let yaw = 0
let pitch = 0

export function main() {
	// a entity seguida pela câmera
	cameraEntity = engine.addEntity()
	Transform.create(cameraEntity, { position: Vector3.create(8, 3, 8) })
	VirtualCamera.create(cameraEntity, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(0.5) },
	})

	// clique nesta caixa para entrar no modo mouselook
	const box = engine.addEntity()
	Transform.create(box, { position: Vector3.create(8, 1, 4) })
	MeshRenderer.setBox(box)
	MeshCollider.setBox(box)
	pointerEventsSystem.onPointerDown(
		{
			entity: box,
			opts: { button: InputAction.IA_POINTER, hoverText: 'Control camera' },
		},
		() => activateCamera(true)
	)

	// controle a câmera com o mouse
	engine.addSystem(() => {
		if (!cameraActive) return
		if (!PointerLock.getOrNull(engine.CameraEntity)?.isPointerLocked) return

		const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
		if (!delta) return

		yaw += delta.x * SENSITIVITY
		// limite o pitch para que a câmera não possa virar
		pitch = Math.max(-85, Math.min(85, pitch - delta.y * SENSITIVITY))

		Transform.getMutable(cameraEntity).rotation = Quaternion.fromEulerDegrees(pitch, yaw, 0)
	})

	// saia do modo mouselook com o botão secundário
	engine.addSystem(() => {
		if (!cameraActive) return
		if (inputSystem.isTriggered(InputAction.IA_SECONDARY, PointerEventType.PET_DOWN)) {
			activateCamera(false)
		}
	})
}

function activateCamera(active: boolean) {
	cameraActive = active

	// atribua ou libere a virtual camera
	MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: active ? cameraEntity : undefined,
	})

	// congele o avatar enquanto a câmera está sendo controlada
	InputModifier.createOrReplace(engine.PlayerEntity, {
		mode: InputModifier.Mode.Standard({ disableAll: active }),
	})

	// bloqueie o cursor, para que o mouse controle a câmera imediatamente
	PointerLock.createOrReplace(engine.CameraEntity, { isPointerLocked: active })
}
```

Alguns pontos a observar neste exemplo:

* O system subtrai `delta.y` do pitch, para que mover o mouse para cima incline a câmera para cima. Inverta esse sinal se preferir controles verticais invertidos.
* O pitch é limitado a uma faixa de -85 a 85 graus, para que a câmera nunca possa virar completamente para trás.
* O `SENSITIVITY` constante expressa graus de rotação por pixel de movimento do mouse; ajuste-a como preferir.

{% hint style="info" %}
**💡 Dica**: O jogador pode desbloquear o cursor a qualquer momento pressionando *Esc* ou clicando com o botão direito, o que faz a câmera parar de responder ao mouse. Sempre ofereça aos jogadores uma forma clara de sair completamente do modo de câmera, como o botão secundário no exemplo acima. Você também pode bloquear o cursor novamente pelo código, veja [Bloquear ou desbloquear o cursor](/creator/content-creator-pt/scenes-sdk7/interatividade/button-events/click-events.md#lock-or-unlock-the-cursor).
{% endhint %}

## Tópicos relacionados

Para ler a posição absoluta do cursor na tela em vez do seu movimento, use a `screenCoordinates` propriedade do mesmo componente. Veja [Verificar a posição do cursor do jogador](/creator/content-creator-pt/scenes-sdk7/interatividade/user-data.md#check-the-players-cursor-position).

Para descobrir qual entity está sob o cursor, combine a `worldRayDirection` propriedade com um raycast. Veja [Raycasting](/creator/content-creator-pt/scenes-sdk7/interatividade/raycasting.md).

{% hint style="info" %}
**💡 Dica**: Para exemplos funcionais do estado do ponteiro, veja a [`0,5-primary-cursor-info`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,5-primary-cursor-info) cena de teste, que lê `PrimaryPointerInfo` em cada frame e alimenta `worldRayDirection` em um raycast; [`31,20-pointer-lock-control`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/31,20-pointer-lock-control), que solicita e libera a captura do cursor escrevendo `PointerLock.isPointerLocked`; e [`32,20-virtual-camera-mouse-look`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/32,20-virtual-camera-mouse-look), que mostra `screenDelta` ainda reportando movimento enquanto `screenCoordinates` está fixado no centro da tela durante o bloqueio.
{% 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 dynamically by asking a question.

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

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/mouse-movement.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
