> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.sayduck.com/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# 3D Viewer - API documentation

# 3D Viewer API

The sayduck viewer exposes an api object with various methods that you can use to interact with the sayduck viewer.
There are two methods to access the viewer api.

1. Listen for the `sayduck.api-ready` event (Recommended)

```javascript
let api;
window.addEventListener('sayduck.api-ready', (event) => {
    api = (event as CustomEvent).detail.instance;
});
```


2. Invoke the `sayduck.request-api` event

```javascript
async function getViewerApi() {

  const request = new CustomEvent('sayduck.request-api', {
    bubbles: true,
    composed: true,
    detail: {
      instance: {},
    },
  });
  window.dispatchEvent(request);
  const api = await request.detail.instance;
  return api;
}
```

### glTF Loaded

`sayduck.editor.gltfLoaded`
Sent when the 3D Viewer has finished loading.

# Variants API

Functionality related to **variants** is available on the configurator (`api.variants`) property of the api and is only available when viewer `mode` attribute is set to `variants`.

```html
<sayduck-viewer product="product-uuid" 
  mode="variants"
>
</sayduck-viewer>
```

### Change variant 

`api.variants.setActiveVariant("variant-uuid");`
Set active variant to input.

### List variant UUIDs

`api.variants.getVariants();`
List all variant uuids, names and metadata.

# Configurator API

Functionality related to **configurator** is available on the configurator (`api.configurator`) property of the api and is only available when viewer `mode` attribute is set to `configurator`.

```html
<sayduck-viewer product="product-uuid" 
  mode="configurator"
>
</sayduck-viewer>
```

### Get configuration values

`api.configurator.getConfigurations(): ConfigurationObject[]`
Lists all the configuration and it's variants/configurations and their children, useful when creating a custom picker.

```typescript
export interface ConfigurationObject {

  uuid: string;
  name: string;
  label: string | null;
  children?: ConfigurationObject[];
  isOptional?: boolean;
  isConfiguration?: boolean;
  parent: {
    uuid: string;
    name: string;
  } | null;
  selectedVariant?: {
    uuid: string | null;
    name: string | null;
  };
}
```

### Change variant / configuration

`api.configurator.setActiveByUuid("variant-uuid" | "configuration-uuid");`
Note: Setting a configuration uuid instead of the variant will select the first variant of that configuration

### List selected variants

`api.configurator.getSelectedVariants();`
List selected variant uuids, names and metadata.

### List selected variant uuids

`api.configurator.getSelectedVariantUuids();`
List selected variants uuids.

### Disable optional configuration

`api.configurator.disableConfiguration("configuration-uuid");`
Disable configuration that is marked optional.

### Create a simple picker

`api.configurator.createPicker(): HTMLElement`
This will create a simple picker with buttons that change the variants.
The elements themselves won't have any styling, you need to style them for yourself.
If you want more control over how the picker works/looks it's recommended to create your own picker.
Here's a list of classes of the elements created:

`sayduck-picker` - Container element
`sayduck-configuration` - Configuration
`sayduck-configuration-label` - Configuration label
`sayduck-variant-button` - Variant button
`sayduck-variant-button-active` - Variant active

# Scene API

Functionality related to **scene** is available on the configurator (`api.scene`) property of the api and is only available for both viewer `mode` attribute `configurator` & `variants` .

### Load new product without reloading page

`api.scene.update3dViewer(productUuid: string, mode: APP_MODE);`
Load new product without reloading page.

### Augmented reality (AR)

###### Launch AR (menu)

`api.scene.launchWebAr();`
Launch AR on the active scene when trigged on mobile.

###### Request QR code URL

`api.scene.getQrCodeUrl();`
Requests QR code URL that can then be used to integrate custom QR code elements.

### Dimensions

###### Toggle dimensions (menu)

`api.scene.toggleDimensions();`
Triggers Dimensions in the action menu.

###### Load dimensions on selected configurations

The new function expects an array of configurations UUIDS and it returns the dimensions of the selection.
Optionally showDimensionsInViewer can be passed, making the output dimensions visible in the scene.

```javascript
const configurationUuids = ['abc', 'def']
const showDimensionsInViewer = true

api.configurator.getConfigurationDimensions = (
    configurationsUuids,
    showDimensionsInViewer,
  )
```
It can be also used to get the dimensions of a single configuration by passing only one element to the uuids array.

### Camera

###### Change camera angle

`api.scene.setCameraAngles(horizontalAngle, verticalAngle)`
Sets camera angle to set value (-180-180).

###### Toggle camera position (menu)

`api.scene.toggleCameraPositions();`
Triggers Camera Positions in the action menu

###### Load camera position

`api.scene.setActiveCamera("camera-uuid")`
Sets the camera to a set camera position.

### Screenshot

###### Screenshot as data url
```typescript
  api.scene.requestScreenshot(
        format?: 'png' | 'jpeg';
        keepPosition?: boolean; // Keep position of camera
        horizontalAngle?: number;
        verticalAngle?: number;
        width?: number;
        height?: number;
    ): string
```
`api.scene.requestScreenshot().then(data => console.log(data));`
Lists event details to console.

**Example data received:**
```json
{
  dataUrl: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...",
  verticalAngle: 15,
  horizontalAngle: -35,
}
```
###### Take screenshot (menu)

`api.scene.takePhoto({ download: boolean });`
Triggers Screenshot in the action menu.

### Lights

###### Toggle lights (menu)

`api.scene.toggleLights();`
Triggers Toggle Lights in the action menu.

### Annotations

###### Toggle annotations (menu)

`api.scene.toggleAnnotations();`
Triggers Annotations in the action menu.

###### Select annotation by uuid

`api.scene.selectAnnotation(variant-uuid);`
Loads selected annotation.

###### Unselect annotation

`api.scene.unselectAnnotation();`
Unselect the selected annotation.

# 3D Text (troika-three-text)

Create and customize your 3D text using the **troika-three-text** package attributes.
More information on the feature can be found: https://www.npmjs.com/package/troika-three-text

### Update text node

`api.scene.updateTextNode(text: string)`
Set 3D text to set value.

### Update text styling

All of these fields are optional.
```typescript
api.scene.updateTextNodeAttributes(attributes: {
    anchorX: number;
    anchorY: number;
    clipRect: string;
    color: ColorRepresentation;
    curveRadius: number;
    depthOffset: number;
    direction: 'auto' | 'rtl' | 'ltr';
    fillOpacity: number;
    font: string;
    fontSize: number;
    glyphGeometryDetail: number;
    letterSpacing: number;
    lineHeight: 'normal' | number;
    maxWidth: number;
    outlineBlur: number;
    outlineColor: ColorRepresentation;
    outlineOffsetX: number;
    outlineOffsetY: number;
    outlineOpacity: number;
    outlineWidth: number;
    overflowWrap: 'normal' | 'word-wrap';
    sdfGlyphSize: number;
    strokeColor: ColorRepresentation;
    strokeOpacity: number;
    strokeWidth: number;
    textAlign: string;
    textIndent: number;
    whiteSpace: 'normal' | 'nowrap';
}): void
```
# Dynamic Material API

### How to use?
```javascript
console.log(api.scene.getAllMaterialUuids()); // Get all materials

// Update albedoColour
api.scene.updateMaterial("material-uuid", {
  albedoColour: { red: 255, green: 0, blue: 0 },
});
// Change texture
api.scene.updateMaterial("material-uuid", {
  albedoTexture:
    "[https://example.com/link-to-texture.jpg](https://example.com/link-to-texture.jpg)",
});
// Update multiple fields
api.scene.updateMaterial("material-uuid", {
  albedoColour: { red: 255, green: 0, blue: 0 },
  metalness: 1,
  roughness: 0,
  emissiveColour: { red: 0, green: 0, blue: 200 },
});
```
**Example integration:** https://jsfiddle.net/5d3aeub4/

### Update material

`api.scene.updateMaterial(materialUuid, {})`
Updates Material properties.

### Material fields

* albedoColour: `{ red: number; green: number; blue: number; alpha: number; }`
* hasAlbedoTransparency: `boolean;`
* albedoTexture: `'https://example.com/link-to-texture.jpg'`
* metalness: `number;`
* metalnessTexture: `'https://example.com/link-to-texture.jpg'`
* roughness: `number;`
* roughnessTexture: `'https://example.com/link-to-texture.jpg'`
* normalTextureIntensity: `number;`
* normalTexture: `'https://example.com/link-to-texture.jpg'`
* occlusionTextureIntensity: `number;`
* occlusionTexture: `'https://example.com/link-to-texture.jpg'`
* emissiveColour: `{ red: number; green: number; blue: number; }`
* emissiveTextureIntensity: `number;`
* emissiveTexture: `'https://example.com/link-to-texture.jpg'`

### Material updated

`sayduck.viewer.material.updated`
Sent when material update is visible in the 3D Viewer

### Extension fields

###### Volume

`volumeExtension` needs to be set to true

* volumeExtension: `boolean;`
* thicknessTexture: `'https://example.com/link-to-texture.jpg'`
* attenuationColour: `{ red: number; green: number; blue: number; }`
* thicknessFactor: `number;`
* attenuationDistance: `number;`

###### Clear coat

`clearcoatExtension` needs to be set to true

* clearcoatExtension: `boolean;`
* clearcoatFactor: `number;`
* clearcoatRoughnessFactor: `number;`
* clearcoatTexture: `'https://example.com/link-to-texture.jpg'`
* clearcoatNormalTexture: `'https://example.com/link-to-texture.jpg'`
* clearcoatRoughnessTexture: `'https://example.com/link-to-texture.jpg'`

###### Ior

`iorExtension` needs to be set to true

* iorExtension: `boolean;`
* ior: `number;`

###### Sheen

`sheenExtension` needs to be set to true

* sheenExtension: `boolean;`
* sheenTexture: `'https://example.com/link-to-texture.jpg'`
* sheenRoughnessTexture: `'https://example.com/link-to-texture.jpg'`
* sheenColour: `{ red: number; green: number; blue: number; }`
* sheenRoughnessFactor: `number;`

###### Transmission

transmissionExtension needs to be set to true

* transmissionExtension: `boolean;`
* transmissionFactor: `number;`
* transmissionTexture: `'https://example.com/link-to-texture.jpg'`

###### Transform (tiling)
transformExtension needs to be set to true

* transformExtension: `boolean;`
* tiling: `{ x: number; y: number; }`
* tilingOffset: `{ x: number; y: number; }`
* tilingRotation: `{ x: number; y: number; }`


# Dynamic TRS API

### How to use?
```javascript
console.log(api.scene.getAllNodeUuids()) // get all node uuids

  api.scene.updateNode("node-uuid", {
    translation: { x: 1, y: 1, z: 1 },
    rotation: { x: 0, y: 0, z: 180 },
    scale: { x: 2, y: 2, z: 2 }
  })
```
**Example integration:** https://jsfiddle.net/07wx1uq3/

### Get all node uuids

`console.log(api.scene.getAllNodeUuids())`

### Update node
```javascript
api.scene.updateNode("node-uuid", {
    translation: { x: 1, y: 1, z: 1 },
    rotation: { x: 0, y: 0, z: 180 },
    scale: { x: 2, y: 2, z: 2 }
  })
```
### Fields

* translation: `{ x: number; y: number; z: number; }`
* rotation: `{ x: number; y: number; z: number; }`
* scale: `{ x: number; y: number; z: number; }`

```
```