# Getting Started With Scripting

> Learn how to use the Python API in Asset Transformer Studio

Learn how to use the Python API to automate tasks in Asset Transformer Studio.

Whether you want to script short helper functions or plugins, this document should help you get started or improve your knowledge.

## Tools

In this document, we use the [Script panel](../../user-interface/window/scripting) as scripting tool, but feel free to use your preferred IDE.

> **Note:**
>
> When using your preferred IDE for development you will suffer from lack of autocompletion. Have a look at [our custom workaround](https://gitlab.com/pixyz/samples/studio/ide-auto-completion) to generate static autocompletion libraries for Visual Code, Sublime or PyCharm.

All API functions are listed in the [API Reference](/asset-transformer-studio/2026.5.0/api/python/studio_functions.md), but also directly in Asset Transformer Studio [Function List](../../user-interface/menu-bar/edit-menu/function-list). This tool is particularly useful to find methods from keywords, go to their documentation and access parameters and returned types, but also to copy and paste Python code:

![Script panel](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python.png)

## Structure

Consider that anything doable via a human interaction in Asset Transformer Studio is doable through the API.

To understand the logic of Asset Transformer Studio scripting you must understand the structure behind it:

![Asset Transformer Studio entity structure (simplified)](/api/media?file=/asset-transformer-studio/2026.5.0/media/api-diagram.png)

*Asset Transformer Studio entity structure (simplified)*

### Entities

Entities are abstract objects defined by an integer *ID* (meaning that an occurrence, a material or a component will all have an ID). Each ID is unique and most functions take this ID or a list of IDs as input. Some functions such as `core.getProperty`, `core.setProperty`, or `core.listProperties` take all types of entities as input — meaning that you'll use the same function to access an occurrence, a material or a part property:

![core.getProperty(3, 'Visible') → 'Inherited'](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python-1.png)

![core.getProperty(15, 'color') → '\[0, 1, 1, 1\]'](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python-2.png)

*core.getProperty(15, 'color') → '\[0, 1, 1, 1]'*

> **Note:**
>
> Use `eval(…)` to convert the returned string value of `getProperty` into a list (e.g. for the `color` property) or a list of lists (e.g. for the `Transform` property).

### Occurrences

[Occurrences](../../data-preparation-fundamentals/about-occurrences/occurrence-types) are the nodes in the product structure, they can have children and prototypes. Most of the optimization functions take an occurrence or a list of occurrences as input. For example:

* `algo.tessellate([1], …)` will apply on all children of `1`.
* To retrieve the root occurrence in your scene you can use the `scene.getRoot()` function.
* To find occurrences based on a property you can use the `scene.findOccurrencesByProperty(property, regex)` function.

Properties defining occurrences can be visualized in the [Inspector](../../user-interface/window/inspector) (ID, Name, Visible, Material, Transform…).

> **Note:**
>
> A useful way to retrieve all occurrences in your scene, or recursive children of an occurrence is to use the `findOccurrencesByProperty` method with the `Name` property and `.*` as a regex: `scene.findOccurrencesByProperty('Name', '.*', [scene.getRoot()])`.
> ⇒ Find all the Occurrences, with the Property Name= anything, among the Occurrences that compose the Root of the scene (= all the occurrences).

> **Note:**
>
> To only retrieve part occurrences (occurrences containing a part component) use `scene.getPartOccurrences(root)`.

### Components

[Components](../../data-preparation-fundamentals/about-occurrences/occurrence-components) are behaviors attached to occurrences. Their IDs can be retrieved thanks to the `scene.getComponent(occurrence, componentType)` or the `scene.getComponentByOccurrence(listOfOccurrences, componentType)` methods (value is 0 if does not exist for the second method). Component types are listed in the `scene.ComponentType` enum. You can visualize the components in the Inspector below the occurrence properties:

![Components example](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python-4.png)

### Metadata

Metadata are components storing basic key/value information retrieved in the imported files. You can add, modify, and delete metadata through the API. You can either use `core.listProperties` or `core.getProperty` to access this information or directly extract it using `scene.getMetadatasDefinitions(listOfMetadataComponents)`. You can also use `scene.findByMetadata(property, regex)` to retrieve occurrences based on metadata.

```python
occurrences = scene.findByProperty('Name', '.*')
metadataComponents = scene.getComponentByOccurrence(occurrences, scene.ComponentType.Metadata)
metadataDefinitions = scene.getMetadatasDefinitions(metadataComponents)

for occurrence, definition in zip(occurrences, metadataDefinitions):
    print(f'Occurrence {occurrence} contains {len(definition)} metadata')
    for propValue in definition:
        print(f'{propValue.name}:{propValue.value}')
```

### Part

Part components contain geometry information (CAD, mesh, lines, UVs…). For example, to retrieve mesh definitions from a list of occurrences:

```python
partComponents = scene.getComponentByOccurrence(occurrences, scene.ComponentType.Part)
for occurrence, partComponent in zip(occurrences, partComponents):
    if partComponent != 0: # meaning the corresponding occurrence did not have any part attached
        mesh = scene.getPartMesh(partComponent)
        meshDef = polygonal.getMeshDefinition(mesh)
        vertices = meshDef.vertices # MeshDefinition is a structure, its attributes can be found in the API documentation
```

### Materials

Materials are entities containing visual definitions. They can be interactively accessed from the Material Editor. They are defined by a pattern and properties specific to each pattern.

![Available patterns](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python-5.png)

When creating a material from script, a pattern is required: fill it with one of the above ones depending on which type of material you want to create (`material.createMaterial("Standard Material", "standard")`).

When modifying from script a material defined by complex properties, it can be hard to understand how to fill the value parameters of `core.getProperty`. For example the **diffuse** value of a standard material:

![Diffuse property example](/api/media?file=/asset-transformer-studio/2026.5.0/media/script-in-python-6.png)

In this case you can print in the console the **diffuse** value of an existing material by just executing: `print(core.getProperty(49, 'diffuse'))`, which will output `COLOR([0.000000, 0.000000, 0.000000])`. So to modify a diffuse texture proceed as follows: `core.setProperty(materialId, 'COLOR(' + str(YOUR_VALUES) + ')')`.

For example, here is a script to assign materials based on a metadata:

```python
def assignMaterialsFromMetadata():
    existingMaterials = {core.getProperty(mat, 'Name'):mat for mat in material.getAllMaterials()}
    filteredOccurrences = scene.findOccurrencesByMetadata('CAD_MATERIAL', '.*')
    filteredMetadata = scene.getComponentByOccurrence(filteredOccurrences, 5, True)
    for occurrence, metadata in zip(filteredOccurrences, filteredMetadata):
        materialName = scene.getMetadata(metadata, 'CAD_MATERIAL')
        if materialName in existingMaterials.keys():
            core.setProperty(occurrence, 'Material', str(existingMaterials[materialName]))
        else:
            newMaterial = material.createMaterial(materialName, 'color')
            core.setProperty(newMaterial, 'color', str([0.5, 0.5, 0.5, 1]))
            core.setProperty(occurrence, 'Material', str(newMaterial))
            existingMaterials[materialName] = newMaterial

assignMaterialsFromMetadata()
```

## Tips

* Sample scripts are accessible in the Asset Transformer Studio installation folder (`doc/Sample Scripts`).

* To search the Python API documentation offline, use the **[pixyz-api-search](https://github.com/bradscottUNITY/pixyz-api-search)** tool. This tool supports partial matches.

* When parsing a large number of occurrences, thousands of logs will be written in the console. It can slow down your process or even freeze Asset Transformer Studio. You can disable the logs by using the `core.configureInterfaceLogger` function. Don't forget to re-enable them at the end.

* Generate your own progression steps by using the `core.pushProgression` and `core.stepProgression` methods:

  ```python
  allPartOccurrences = scene.getPartOccurrences()
  core.pushProgression(len(allPartOccurrences))
  for occurrence in allPartOccurrences:
      # ...
      core.stepProgression()
  core.popProgression()
  ```

* When retrieving a structure from a method (e.g. `scene.getAABB(occurrences)`), you can check the documentation to get the attributes names (e.g. [AABB.low](/asset-transformer-studio/2026.5.0/api/python/geom_types.md#aabb) and [AABB.high](/asset-transformer-studio/2026.5.0/api/python/geom_types.md#aabb)):

  ```python
  aabb = scene.getAABB([scene.getRoot()])
  print(f'Higher x values: {aabb.high.x}')
  ```

* To import custom modules: Import custom Python modules in Studio

* Most preferences are shared between Asset Transformer products. To change them from script, use the `core.setModuleProperty` method:

  ```python
  core.setModuleProperty('IO', 'PreferLoadMesh', 'True')
  ```
