# Gizmos

> Learn about gizmos in Babylon.js.

Source: https://doc.babylonjs.com/features/featuresDeepDive/mesh/gizmo

## Introduction

Gizmos are objects that can be attached to a node (mesh, bone, transform) to provide interaction. The GizmoManager and BoundingBox gizmo work with meshes, whereas position, scale, and rotation gizmos are also usable with TransformNodes and Bones.

![Babylon.js Gizmos](https://doc.babylonjs.com/img/how_to/gui/gizmos.webp)

Note: BoundingBox Gizmo will set/modify the [rotationQuaternion](https://doc.babylonjs.com/features/featuresDeepDive/mesh/transforms) of the attached node. After attaching, any rotation of the mesh should be done with the rotationQuaternion property instead of rotation.

## GizmoManager

To get a default gizmo setup, the GizmoManager class can be used.

```javascript
const gizmoManager = new BABYLON.GizmoManager(scene);
```

The gizmo manager will attach the enabled gizmo to whatever object in the scene that is selected by a pointer. To enable a gizmo, any of the following can be used:

```javascript
gizmoManager.positionGizmoEnabled = true;
gizmoManager.rotationGizmoEnabled = true;
gizmoManager.scaleGizmoEnabled = true;
gizmoManager.boundingBoxGizmoEnabled = true;
```

To specify the meshes which can have the gizmo attached, the attachableMeshes field can be set.

```javascript
gizmoManager.attachableMeshes = [mesh1, mesh2, mesh3];
```

To manually change the selected mesh, the gizmo manager's _attachToMesh_ method can be called and the usePointerToAttachGizmos field can be used to disable the manager's default pointer behavior.

```javascript
gizmoManager.usePointerToAttachGizmos = false;
gizmoManager.attachToMesh(mesh);
```

All the internal gizmos are accessible through the manager to support scenarios such as listening to drag events.

```javascript
gizmoManager.gizmos.scaleGizmo;
gizmoManager.gizmos.rotationGizmo;
gizmoManager.gizmos.positionGizmo;

gizmoManager.gizmos.positionGizmo.xGizmo.dragBehavior.onDragStartObservable.add(() => {
  console.log("Position gizmo's x axis started to be dragged");
});
gizmoManager.gizmos.positionGizmo.xGizmo.dragBehavior.onDragEndObservable.add(() => {
  console.log("Position gizmo's x axis drag was ended");
});
```

By default, gizmo orientation is in local space, so it is rotated to match the rotation of the object it is attached to. To switch to world orientation, set the `updateGizmoRotationToMatchAttachedMesh` property to `false`:

```javascript
gizmoManager.gizmos.positionGizmo.updateGizmoRotationToMatchAttachedMesh = false;
```

Note: This is not supported on the scale gizmo

- [Playground: Gizmo Manager Example](https://playground.babylonjs.com/#4TBMBR#33) - Simple example of using the gizmo manager.

## Setup

Gizmos are displayed by a [UtilityLayerRenderer](https://doc.babylonjs.com/features/featuresDeepDive/mesh/utilityLayerRenderer) to not disrupt the existing scene state. If not specified, the default utility layer will be used.

The utility layers are independent of the scene or engine. After creating a gizmo, it is exposed through `gizmo.gizmoLayer`. If you create a gizmo without specifying a utility layer, it will use the default utility layer’s `UtilityLayerRenderer.DefaultUtilityLayer` for overlay gizmos like position and scale, and `UtilityLayerRenderer.DefaultKeepDepthUtilityLayer` for occluded gizmos like the bounding box. It is recommended to use and reuse these layers in most cases, as every new utility layer comes with additional overhead.

```javascript
const utilLayer = new BABYLON.UtilityLayerRenderer(scene);
const gizmo = new BABYLON.AxisDragGizmo(new BABYLON.Vector3(1, 0, 0), BABYLON.Color3.FromHexString("#00b894"), utilLayer);
```

When created, the gizmo is not attached to a node and is not visible, so it must be attached to a node to become active. Setting this to `null` will disable or hide the gizmo again.

```javascript
gizmo.attachedMesh = sphere;
```

By default, the gizmo is updated to match the attached node's rotation and position, but this can be modified with the following:

```javascript
// Keep the gizmo fixed to world rotation
gizmo.updateGizmoRotationToMatchAttachedMesh = false;
gizmo.updateGizmoPositionToMatchAttachedMesh = true;
```

- [Playground: Gizmo .glTF Setup Example](https://playground.babylonjs.com/#8GY6J8#210) - Simple example of how to set up a gizmo for a .glTF File.

## Position, scale and rotation gizmos

Default gizmos for position, rotation, and scale on a single axis are supported.

- [Playground: AxisDragGizmo Example](https://playground.babylonjs.com/#31M2AP#9) - Simple example of how to use the AxisDragGizmo.
- [Playground: AxisScaleGizmo Example](https://playground.babylonjs.com/#31M2AP#10) - Simple example of how to use the AxisScaleGizmo.
- [Playground: PlaneRotationGizmo Example](https://playground.babylonjs.com/#31M2AP#11) - Simple example of how to use the PlaneRotationGizmo.

Snapping can be enabled on any of the single-axis gizmos.

```javascript
gizmo.snapDistance = 0.3;
gizmo.onSnapObservable.add((event) => {
  console.log(event);
});
```

A sensitivity factor can be customized for AxisScaleGizmo and ScaleGizmo. Default is 1, a higher value means more stretch for the same drag.

```javascript
gizmoScale.sensitivity = 3;
```

These gizmos internally use a [pointerDragBehavior](https://doc.babylonjs.com/features/featuresDeepDive/behaviors/meshBehaviors), which is exposed and can be used to perform tasks before, during, or after dragging a gizmo.

```javascript
gizmo.dragBehavior.onDragObservable.add(() => {
  console.log("drag");
});
```

Classes for three-axis gizmos are also provided, each containing three single-axis gizmos.

- [Playground: PositionGizmo Example](https://playground.babylonjs.com/#31M2AP#6) - Simple example of how to use the PositionGizmo.
- [Playground: ScaleGizmo Example](https://playground.babylonjs.com/#31M2AP#8) - Simple example of how to use the ScaleGizmo.
- [Playground: RotationGizmo Example](https://playground.babylonjs.com/#31M2AP#7) - Simple example of how to use the RotationGizmo.

The single-axis gizmos within these are exposed via the `xGizmo`, `yGizmo`, and `zGizmo` properties. The scale gizmo also has a `uniformScaleGizmo` property that references the center gizmo used for uniform scaling.

## Bounding box Gizmo

The BoundingBoxGizmo displays a bounding box around an object as well as controls to rotate and scale the object.

The enabled rotation axis can be customized with the following:

```javascript
// only enable rotation on x and y axis
gizmo.setEnabledRotationAxis("xy");
```

The size of rotation and scale controls on the gizmo can be adjusted by using the following controls:

```javascript
// The size of the rotation spheres attached to the bounding box (Default: 0.1)
gizmo.rotationSphereSize = 0.1;
// The size of the scale boxes attached to the bounding box (Default: 0.1)
gizmo.scaleBoxSize = 0.1;
// If set, the rotation spheres and scale boxes will increase in size based on the distance away from the camera to have a consistent screen size (Default: false)
gizmo.rotationSphereSize = false;
```

The following events are fired when dragging occurs on either the scale or rotation meshes of the bounding box.

```javascript
gizmo.onScaleBoxDragObservable.add(() => {
  console.log("scaleDrag");
});
gizmo.onScaleBoxDragEndObservable.add(() => {
  console.log("scaleEnd");
});
gizmo.onRotationSphereDragObservable.add(() => {
  console.log("rotDrag");
});
gizmo.onRotationSphereDragEndObservable.add(() => {
  console.log("rotEnd");
});
```

To drag around objects contained inside a bounding box, [Mesh Behaviors](https://doc.babylonjs.com/features/featuresDeepDive/behaviors/meshBehaviors) can be attached.
When using models with complex geometry, such as a custom glTF file, the complex model should be set to not be pickable by pointers and wrapped in a pickable bounding box mesh to improve performance. A helper method is provided for this.

```javascript
const boundingBox = BABYLON.BoundingBoxGizmo.MakeNotPickableAndWrapInBoundingBox(gltfMesh);
```

Additionally, the bounding box can ignore children of the attached mesh for additional performance gains when needed.

```javascript
gizmo.ignoreChildren = true;
```

To only ignore certain children when computing the bounding box, the includeChildPredicate can be set.

```javascript
gizmo.includeChildPredicate = (m) => {
  return m == sphere2;
};
```

- [Playground: Bounding Box Gizmo Example](https://playground.babylonjs.com/#SG9ZZB) - Simple example of a bounding box gizmo.

UI can be attached to the bounding box using the [AttachToBoxBehavior](https://doc.babylonjs.com/features/featuresDeepDive/behaviors/meshBehaviors).

- [Playground: Bounding Box Gizmo .glTF Example](https://playground.babylonjs.com/#8GY6J8#199) - Simple example of how to use the Bounding Box Gizmo with a .glTF file.
- [Playground: Bounding Box Gizmo Animated .glTF Example](https://playground.babylonjs.com/#6E4LSB#15) - Simple example of how to use the Bounding Box Gizmo with an animated .glTF file.
- [Playground: Bounding Box Gizmo Example](https://playground.babylonjs.com/#DEYAQ5#47) - Simple example of how to use the Bounding Box Gizmo.

## Gizmo customization

To customize the visual appearance of an existing gizmo, create a mesh on the same utility layer and then call `setCustomMesh` on the gizmo. Utility layers do not contain lights by default, so it is recommended to use a material with an emissive texture.

```javascript
const customMesh = BABYLON.MeshBuilder.CreateBox("", { size: 0.1 }, gizmo.gizmoLayer.utilityLayerScene);
customMesh.material = material;
gizmo.setCustomMesh(customMesh);
```

- [Playground: Gizmo Customization Example](https://playground.babylonjs.com/#7KX2R8#133) - Simple example of how to customize the gizmo.
