---
title: "Plugins, Classes and Categories API"
canonical: "https://documentation.chaos.com/space/APPSDK/132679006/Plugins%2C%20Classes%20and%20Categories%20API"
format: markdown
---
## "Symmetric" plugins, classes and categories API in Python and Node.js

Disclaimer: This is not a full description of the types, their methods, properties, etc. Only general concepts are described here. For full description of the concrete types and their methods, see the API Reference Guides.

### Python

##### Container objects

Let's have a `VRayRenderer` instance:

```python
import vray
renderer = vray.VRayRenderer()
```

Then

`renderer.plugins` is a container of all plugin instances inside this renderer.

`renderer.classes` is a container of all plugin classes (or types) loaded into and thus supported by this renderer.

`renderer.categories` is a container of all plugin categories to which the plugins may belong. This container is not as essential as the other two but it can be quite useful in some cases.

`renderer.plugins`, `renderer.classes` and `renderer.categories` are custom objects that have some *dictionary-like* features but they are not dictionaries:

1. They support the *mapping protocol* (like dictionaries) - the *keys* in `plugins` are *plugin names*, the *keys* in `classes` are *class names* and the *keys* in `categories` are *category names* e.g. `renderer.plugins['settingsColorMapping']`, `renderer.classes['SettingsColorMapping']`, `renderer.categories['Settings']`.
2. They are *iterable* but the iteration is performed over the `plugin` / `class` / `category` objects they contain (similar to sets) and **not** over their names (like dictionaries).
3. They support access by attribute name so e.g. `renderer.plugins.settingsColorMapping` returns the same object as `renderer.plugins['settingsColorMapping']`, `renderer.classes.SettingsColorMapping` returns the same object as `renderer.classes['SettingsColorMapping']` and `renderer.categories.Settings` returns the same object as `renderer.categories['Settings']`.
4. The `len()` function returns the number of `plugin` / `class` / `category` objects contained in them.

Among these 3 containers (`plugins`, `classes` and `categories`), only `plugins` support *deletion* (removing elements). It is important to note that deleting and creating `plugin` instances during iteration **is** supported so:

```python
for plugin in renderer.plugins: # This is preferred
  if someCondition:
    # Delete the plugin in plugins. Its reference then becomes invalid and 'plugin' is removed from renderer.plugins
    plugin.deleteThis() # plugin.isValid() will return False after this call
    # Alternative way to delete plugin instances
    # del renderer.plugins[plugin] # use the plugin name or the plugin instance as the key
  if otherCondition:
    # Create a new plugin (with an auto-generated name) inside renderer.plugins
    renderer.classes.Node()
```

would work exactly the same as:

```python
for plugin in list(renderer.plugins): # This is redundant and slower
  ...
```

or

```python
for plugin in vray.PluginList(source = renderer.plugins):  # This is redundant and slower 
  ...
```

but would be more efficient. Newly created plugin instances wouldn't be included in the loop but deleted plugins would be included as invalid references (see `plugin.isValid()` method).

Container objects may also include methods e.g.

`renderer.categories.getInstances((renderer.categories.GeometricObject, renderer.categories.Light))`

would return all geometric objects that are lights (or all lights that are also geometric objects, depending on your point of view but it's exactly the same).

#####   
Plugin objects, class objects and category objects

These 3 share similar characteristics as well (although category objects are closer to the container objects described above, see their description below).

#### Plugin objects

The *plugin objects* are *references* (or *handles*) to *plugin instances* inside a `VRayRenderer` instance. The *plugin parameters* are presented as both *attributes* and *keys* on the plugin objects. They are always read and written by *value* which means that when you read them, you get a **copy** of the whole value contained inside them (even if it's a complex value like a list) and when you write to them, you set a **copy** of their value inside the corresponding plugin parameter.

*Plugin objects* act both as plugin handles used to manipulate their plugin parameters (via their *attributes*, *keys* or *getter*/*setter* methods) and *plugin references* that can be set as values to other plugin parameters.

*Plugin objects* are *dictionary-like* custom types. Iterating over a plugin object iterates over its **parameter names** similar to dictionaries. Note that this behavior is different from the behavior of the `renderer.plugins`, `renderer.classes` and `renderer.categories` containers where iteration is performed over the values they contain (i.e. *plugin*, *class* or *category* objects) and not the keys.

Besides keys and attributes a *plugin object* also have methods to perform various actions upon the underlying plugin instance or to query some info about it.

*Plugin objects* may be (or become) *invalid* if/when/after the underlying plugin instance is deleted.

#### PluginRef objects

The `PluginRef` type is an extension of `Plugin`. Its whole purpose is to refer to *alternative plugin outputs*. Some plugins (e.g. textures), when used as inputs to other ones, generate data of a certain type (e.g. `AColor`) but might have additional outputs (called *output parameters* and designated by `pluginName::outputParamName` in the .vrscene files) of other types (e.g. `float`, `int`, etc.). A `PluginRef` object consists of a *plugin object* and an *alternative output parameter* of that plugin. While `PluginRef`s could be used to manipulate the parameters of the underlying plugin, their real purpose is to be used as *values* of other plugin input parameters.

Have in mind that even if a *plugin* and a *pluginRef object* refer to the same plugin instance inside a `VRayRenderer`, the comparison `plugin == pluginRef` will be `False`.  
(But `plugin == pluginRef.getPlugin()` and `plugin.getPlugin() == pluginRef.getPlugin()` will be `True`.)

#### Class objects

*Class objects* represent the plugin types. They are mostly used to create plugin instances and query some info about the plugin and/or its parameters without creating a plugin instance.


```python
# Create a plugin of type Node with the name 'myNode1' and assign a reference to it to variable node
node = renderer.classes.Node('myNode1')

# Create a plugin of type Node with the name 'myNode2'
renderer.classes.Node('myNode2')

# In both cases the new plugin becomes available in renderer.plugins
node1 = renderer.plugins.myNode1
node2 = renderer.plugins.myNode2

# Comparisons
node == node1 # Compare plugin instances. This would be True
node == node2 # Compare plugin instances. This would be False
node.getClass() == node2.getClass() # Compare plugin classes. This would be True
node.getClass() == renderer.classes.Node # Compare plugin classes. This would be True
```


*Class objects* are *iterable* over the *parameter names* of the plugin type they represent (similar to plugin objects). Currently accessing the class attributes or keys using the parameter names returns the same data as calling the `class.getMeta(paramName)` method. But you shouldn't rely on this behavior and should always call the `getMeta()` method explicitly because the behavior may change in the future.

*Class objects* also have methods to create or get plugin objects of their type or to query some info about them or their parameters.

#### Category objects

*Category objects* group similar plugin types with similar characteristics. They are contained inside `renderer.categories`. One plugin (instance or class) can belong to none, one or more plugin categories.

The *category objects* are more akin to the `renderer.classes` container because they group the *plugin classes* which belong to them.

Category objects:

1. Support the *mapping protocol* (like dictionaries) - their keys are *class names* e.g. `renderer.categories.GeometricObject['Node']`.
2. Are *iterable* but the iteration is performed over the *class objects* they contain (similar to sets) and **not** over the class names (like dictionaries).
3. Support access by attribute name so e.g. `renderer.categories.GeometricObject.Node` returns the same object as `renderer.categories.GeometricObject['Node']`.
4. Are *indexable*, which is similar to supporting the sequence protocol. `len(category)` returns the number of classes belonging to that category.
5. Have methods to return the plugin objects belonging to them (`category.getInstances()`) or check if a plugin instance or a class belongs to them (`category.belongs(object)`).

### Node.js

##### Container objects

Let's have a `VRayRenderer` instance:

```javascript
const vray = require('./node/vray');
let renderer = new vray.VRayRenderer;
```

Then

`renderer.plugins` is a container of all plugin instances inside this renderer.

`renderer.classes` is a container of all plugin classes (or types) loaded into and thus supported by this renderer.

`renderer.categories` is a container of all plugin categories to which the plugins may belong. This container is not as essential as the other two but it can be quite useful in some cases.

`renderer.plugins`, `renderer.classes` and `renderer.categories` are custom objects:

1. Their *properties* are the `plugin` / `class` / `category` objects contained in them.
2. They are *enumerable* and support `for...in` loops by keys (i.e. `plugin` / `class` / `category` *names*).
3. They are *iterable* and support `for...of` loops by values (i.e. the `plugin` / `class` / `category` *objects* they contain).
4. They support access by property name e.g. `renderer.plugins.settingsColorMapping` or `renderer.plugins['settingsColorMapping']`, `renderer.classes.SettingsColorMapping` or `renderer.classes['SettingsColorMapping']` and `renderer.categories.Settings` or `renderer.categories['Settings']`.
5. Their .`length` property returns the number of `plugin` / `class` / `category` objects contained in them.
6. They may have methods which are **not** included in the enumeration.

Among these 3 containers (`plugins`, `classes` and `categories`), only `plugins` support *deletion* (removing elements). It is important to note that deleting and creating `plugin` instances during iteration **is** supported so:

```javascript
for (let plugin of renderer.plugins) { // This is preferred
  if (someCondition {
    // Delete the plugin in plugins. Its reference then becomes invalid and 'plugin' is removed from renderer.plugins
    plugin.deleteThis(); // plugin.isValid() will return false after this call
    // Alternative way to delete plugin instances
    // delete renderer.plugins[plugin]; // use the plugin name or the plugin instance as the key
  }
  if (otherCondition) {
    // Create a new plugin (with an auto-generated name) inside renderer.plugins
    renderer.classes.Node();
  }
}
```

would work exactly the same as e.g.:

```javascript
for (let plugin of Array.from(renderer.plugins)) // This is redundant and slower
  ...
```

but would be more efficient. Newly created plugin instances wouldn't be included in the loop but deleted plugins would be included as invalid references (see `plugin.isValid()` method).

Container objects may also include methods e.g.

`renderer.categories.getInstances([renderer.categories.GeometricObject, renderer.categories.Light]);`

would return all geometric objects that are lights (or all lights that are also geometric objects, depending on your point of view but it's exactly the same).

#####   
Plugin objects, class objects and category objects

These 3 share similar characteristics as well (although category objects are closer to the container objects described above, see their description below).

#### Plugin objects

The *plugin objects* are *references* (or *handles*) to *plugin instances* inside a `VRayRenderer` instance. The *plugin parameters* are presented as *properties* of the plugin objects. They are always read and written by *value* which means that when you read them, you get a **copy** of the whole value contained inside them (even if it's a complex value like a list) and when you write to them, you set a **copy** of their value inside the corresponding plugin parameter (there is one exception, see the note below).

*Plugin objects* act both as plugin handles used to manipulate their plugin parameters (via their *properties* or *getter*/*setter* methods) and *plugin references* that can be set as values to other plugin parameters.

*Plugin objects* are *enumerable* custom types. `for...in` looping through a plugin object iterates over its **parameter names**. `For...of` loops are **not** supported.

A *plugin object* also have methods to perform various actions upon the underlying plugin instance or to query some info about it. Those are not included in the `for...in` loops.

*Plugin objects* can be compared with the operator ==. See the example below in the class objects section.

*Plugin objects* may be (or become) *invalid* if/when/after the underlying plugin instance is deleted.

<span style="color: #ff0000">**Note**</span> about large typed lists:  
The `renderer.maxTypedListsCopyByteSize` property controls whether the contents of V-Ray typed lists (currently `IntList`, `FloatList`, `ColorList` and `VectorList`) is copied to the corresponding plugin parameter. The default value is `-1` which means to always copy all the data. If you set it to `0` or a *positive number*, the contents data won't be copied if its size in bytes is larger than the number set. Instead, it will be directly set inside the V-Ray memory and the underlying ArrayBuffer will be shared between V-Ray and your program.

#### PluginRef objects

The `PluginRef` type is an extension of `Plugin`. Its whole purpose is to refer to *alternative plugin outputs*. Some plugins (e.g. textures), when used as inputs to other ones, generate data of a certain type (e.g. `AColor`) but might have additional outputs (called *output parameters* and designated by `pluginName::outputParamName` in the .vrscene files) of other types (e.g. `float`, `int`, etc.). A `PluginRef` object consists of a *plugin object* and an *alternative output parameter* of that plugin. While `PluginRef`s could be used to manipulate the parameters of the underlying plugin, their real purpose is to be used as *values* of other plugin input parameters.

*PluginRef* objects can be compared with the operator == too. Have in mind that even if a *plugin* and a *pluginRef* object refer to the same plugin instance inside a VRayRenderer, the comparison `plugin == pluginRef` will be `false`. (But `plugin == pluginRef.getPlugin()` and `plugin.getPlugin() == pluginRef.getPlugin()` will be `true`.)

#### Class objects

*Class objects* represent the plugin types. They are mostly used to create plugin instances and query some info about the plugin and/or its parameters without creating a plugin instance.


```javascript
// Create a plugin of type Node with the name 'myNode1' and assign a reference to it to variable node
var node = renderer.classes.Node('myNode1')

// Create a plugin of type Node with the name 'myNode2'
renderer.classes.Node('myNode2')

// In both cases the new plugin becomes available in renderer.plugins
var node1 = renderer.plugins.myNode1
var node2 = renderer.plugins.myNode2

// Comparisons
node == node1 // Compare plugin instances. This would be true
node == node2 // Compare plugin instances. This would be false
node.getClass() == node2.getClass() // Compare plugin classes. This would be true
node.getClass() == renderer.classes.Node // Compare plugin classes. This would be true
```


*Class objects* are *enumerable* custom types. `for...in` looping through a class object iterates over the *parameter names* of the plugin type they represent.

*Class objects* also have methods to create or get plugin objects of the plugin type they represent, to query some info about the corresponding plugin type and its parameters. Those are not included in the `for...in` loops.

*Class objects* can be compared with the operator ==. See the example above.

Currently accessing the class properties using the parameter names returns the same data as calling the `class.getMeta(paramName)` method. But you shouldn't rely on this behavior and should always call the `getMeta()` method explicitly because the behavior may change in the future.

#### Category objects

*Category objects* group similar plugin types with similar characteristics. They are contained inside `renderer.categories`. One plugin (instance or class) can belong to none, one or more plugin categories.

The *category objects* are more akin to the `renderer.classes` container because they group the *plugin classes* which belong to them.

Category objects:

1. *Properties* are the *plugin classes* which belong to them.
2. Are *enumerable* and support `for...in` loops by *class names*.
3. Are *iterable* and support `for...of` loops over the *class objects* they contain.
4. Support access by both property name (e.g. `renderer.categories.GeometricObject.Node`) and index (e.g. `renderer.categories.GeometricObject[0],` like arrays).
5. Their .`length` property returns the number of `class` objects contained in them.
6. Have methods to return the plugin objects belonging to them (`category.getInstances()`) or check if a plugin instance or a class belongs to them (`category.belongs(object)`).
7. Can be *compared* with the *operator ==*.