"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:
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:
- They support the mapping protocol (like dictionaries) - the keys in
plugins
are plugin names, the keys inclasses
are class names and the keys incategories
are category names e.g.renderer.plugins['settingsColorMapping']
,renderer.classes['SettingsColorMapping']
,renderer.categories['Settings']
. - 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). - They support access by attribute name so e.g.
renderer.plugins.settingsColorMapping
returns the same object asrenderer.plugins['settingsColorMapping']
,renderer.classes.SettingsColorMapping
returns the same object asrenderer.classes['SettingsColorMapping']
andrenderer.categories.Settings
returns the same object asrenderer.categories['Settings']
. - The
len()
function returns the number ofplugin
/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:
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:
for plugin in list(renderer.plugins): # This is redundant and slower ...
or
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.
# 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:
- Support the mapping protocol (like dictionaries) - their keys are class names e.g.
renderer.categories.GeometricObject['Node']
. - Are iterable but the iteration is performed over the class objects they contain (similar to sets) and not over the class names (like dictionaries).
- Support access by attribute name so e.g.
renderer.categories.GeometricObject.Node
returns the same object asrenderer.categories.GeometricObject['Node']
. - Are indexable, which is similar to supporting the sequence protocol.
len(category)
returns the number of classes belonging to that category. - 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:
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:
- Their properties are the
plugin
/class
/category
objects contained in them. - They are enumerable and support
for...in
loops by keys (i.e.plugin
/class
/category
names). - They are iterable and support
for...of
loops by values (i.e. theplugin
/class
/category
objects they contain). - They support access by property name e.g.
renderer.plugins.settingsColorMapping
orrenderer.plugins['settingsColorMapping']
,renderer.classes.SettingsColorMapping
orrenderer.classes['SettingsColorMapping']
andrenderer.categories.Settings
orrenderer.categories['Settings']
. - Their .
length
property returns the number ofplugin
/class
/category
objects contained in them. - 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:
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.:
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.
Note 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.
// 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:
- Properties are the plugin classes which belong to them.
- Are enumerable and support
for...in
loops by class names. - Are iterable and support
for...of
loops over the class objects they contain. - Support access by both property name (e.g.
renderer.categories.GeometricObject.Node
) and index (e.g.renderer.categories.GeometricObject[0],
like arrays). - Their .
length
property returns the number ofclass
objects contained in them. - 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)
). - Can be compared with the operator ==.