Next (Custom Importer) Previous (Logging)


A plugin can be thought of as an addition to existing software so that we can add on specific functions that suit our needs. In, all plugins are written in Javascript. The following describes how to create and write new plugins.

Creating a Plugin

We can create any number of plugins, each of which is stored on the server. We can create a new plugin by following these steps. Please note that to create a plugin, you must first request plugin access. Contact us at to get started!

  1. Click Plugin
  2. Click Create New Plugin
  3. Fill in Name, Version and Description
  4. Write the script contents on the right
  5. Click Save and Submit

Defining a Plugin

To begin, we must name and version our plugin in the script. In we do not include it in your script as you will be filling in the information on the plugin page.

When we load a plugin on the server, it has access to any other files that have also been loaded onto the server.

Defining a Command

A plugin uses a user defined command to execute specific functions. In order to define a command, we must include a name member and an execute function. We can also specify a location for the command in the interface.

  name: 'HelloWorld',
  uiPlace: { menu: ['My Plugin'] },
  uiState: { label: 'Hello World', category: 'hello' },

  execute: function(app, options, callback) {
    alert('Hello, world!');

Defining an Operator

Each scene is made up of multiple nodes which contain many plugs within them. These plugs describe the mesh, material and transformation of the node.The node can be modified / created by an operator. There are two parts to an operator, its name and its target. The name specifies what the operator is called. The target specifies where the operator will plug into.

    name: 'Box',
    target: 'PolyMesh',

Defining a Schema

A schema is used when an input from the user or other parameter is required. Each member is given a type such as ‘Color’ and ‘Text’.

  name: 'Box',
  target: 'PolyMesh',
  schema: {
    // State the type of default value of the size property so the UI knows what to display
    size: {type: 'Vec3', defaultValue: new THREE.Vector3(1, 1, 1), minValue: 0.1, step: 1, animatable: true}

Creation Operator

The creation operator is used to create mesh by using a create function. It allows the vertices and faces of a mesh to be set up.

create: function(operator) {
  // Get the current value of size from the operator instance
  var size = operator.get('size');

  // Use the half size to send into the box so it's centered
  var half = size.clone().multiplyScalar(0.5);
  var positions = [
    new THREE.Vector3(-half.x, -half.y, -half.z),
    new THREE.Vector3(half.x, -half.y, -half.z),
    new THREE.Vector3(half.x, half.y, -half.z),
    new THREE.Vector3(-half.x, half.y, -half.z),
    new THREE.Vector3(half.x, half.y, half.z),
    new THREE.Vector3(half.x, -half.y, half.z),
    new THREE.Vector3(-half.x, half.y, half.z),
    new THREE.Vector3(-half.x, -half.y, half.z)

  var faces = [
    [0, 1, 2, 3],
    [1, 5, 4, 2],
    [3, 2, 4, 6],
    [7, 5, 4, 6],
    [0, 7, 6, 3],
    [0, 1, 5, 7]

  return new exo.geometry.PolyMesh(faces, positions);

Modification Operator

Unlike the creation operator, the modification operator works with existing meshes. It allows us to alter the existing vertices and faces.

modify: function(operator, polyMesh) {
  var aabb = polyMesh.boundingBox();
  var deAlignX = operator.get('deAlignX');
  var deAlignY = operator.get('deAlignY');
  var deAlignZ = operator.get('deAlignZ');
  var halfSize = aabb.size().multiplyScalar(0.5);

  _.each(polyMesh.positions, function(position) {
    if (deAlignX) position.x += halfSize.x;
    if (deAlignY) position.y += halfSize.y;
    if (deAlignZ) position.z += halfSize.z;

  return polyMesh;

Debugging a plugin

Console output from a server side command will be attached to the job (Visible from the Jobs link in your user menu dropdown). Therefore, to debug a plugin running on the server, you can add console.log statements to the command as needed, and verify the output from the stdout.txt file attached to the job.

Next (Custom Importer) Previous (Logging)