Managing Objects

Boxshot lets you create, traverse, edit and delete scene elements (objects) using Javascript. Click the links below to jump to the specific topic.


 

Creating Objects

Creating shapes

Boxshot creates objects inside the scene hierarchy. You can’t just create an object, you have to create it as someone’s child. Usually your objects will be children of the scene root node. To create a sphere object in the root node, run this code:

scene.root.addMesh("sphere", "generator.simple.sphere");

The scene object has the root variable, that you will use very often. The addMesh() method got two parameters: object name and the mesh identifier. The name is up to you, but the identifier has to be correct, as Boxshot uses it to understand which mesh are you going to create.

You can get the identifiers of all the shapes in the shapes scripting tutorial.

Creating omni lights

Omni lights are created the similar way, just using another method:

var l = scene.root.addLight("a light");

Please note that you may assign the created object to a variable to use it later. For example you may set the light position and intensity using the code below:

l.translation  = vec3(10, 20, 30);
l.intensity = 5;

More information about lights scripting is in the special objects tutorial.

Creating groups

Groups are nodes that contains other nodes. They are extremely useful if you’d like to do some animation for several nodes at once. You may rotate some objects around the point, or scale them altogether. The script again looks similar:

scene.root.addGroup("a group");

You may assign the new object to a variable to use it later. You will see some examples below.


 

Traversing the Scene

When you have successfully created some objects, it’s a good idea to find a way to find them in the scene to be able to control their parameters, rename them and so on.

The root node

Each scene has an invisible root node which contains all the top–level nodes. Here’s how you can get it:

var r = scene.root;
print(r.name);

You will see the “Root” in the output window of the Script Editor. Use the root node as a starting point for traversing the scene.

Finding Children

Create some objects in the scene, then run the following code:

var top = scene.root.children;
for (var i in top)
{
	var ch = top[i];
	print("%1: %2", i, ch.name);
}

Here top is the array of children nodes, you may get the number of children this way:

var num = scene.root.children.length;

Each child node itself may have its own children, so you can traverse the whole scene if you like:

function traverse(node, spaces)
{
	var items = node.children;
	for (var i in items)
	{
		var n = items[i];
		print("%1%2", spaces, n.name);
		traverse(n, spaces + "    ");
	}
}
traverse(scene.root, "");

Parent node

Every node has a parent. You can get it this way:

var n = scene.root.addMesh("sphere", "generator.simple.sphere");
print("node: %1", n.name);
print("parent: %1", n.parent.name);

If you run the script, you’ll get this:

node: sphere
parent: Root

Looks correct, the sphere was created in the root node, so its parent is “Root”. But what if we try to get a root’s parent?

var p = scene.root.parent;
print(p);

You will get “null”, as the root node is a topmost one and doesn’t have parents. All the others — have.

Finding Siblings

Now you should know how to find sibling nodes easily. There is no special function for that, as you already have everything you need. Let’s create a sphere and get its neighbors.

var n = scene.root.addMesh("sphere", "generator.simple.sphere");
var siblings = n.parent.children;
print("our sphere has %1 siblings", siblings.length - 1); // we don't count our sphere here, so -1


 

Editing Objects

Now when you can easily traverse the scene, you may want to get or change some parameters of nodes. You may have noticed already that we printed node names while traversing the scene. You may do lots of other things the same way.

Name

Once again, let’s create a sphere, get its name and try to change it:

var n = scene.root.addMesh("sphere", "generator.simple.sphere");
print("current name is %1", n.name);
n.name = "new name";
print("the new name is %1", n.name);

If you run this, you’ll see the following:

current name is: sphere
the new name is: new name

Visibility

Let’s do a more complex task: find and hide all the top-level sphere objects. We already have a good base code above that finds all the top level nodes, let’s modify it to filter spheres and hide them. It takes just three lines:

var top = scene.root.children;
for (var i in top)
{
	var ch = top[i];
	if (ch.type != 1) continue; // 1*
	if (ch.generator.toString().search("Sphere") == -1) continue; // 2*
	ch.visible = false; // 3*
}

This code needs some comments. At the first line (1) we get the node type and check if it is 1. Boxshot supports three types of nodes:

So if the node is not mesh, we simply skip it. The second line (2) is the most complex one. Every mesh node has a generator object that generates a geometry using the provided parameters. So we get each object generator, and check if its name contains a “Sphere” word. If not, we skip it.

Finally, the third line (3) hides the node by setting its visible property to false. To show nodes run the same script with true instead of false.

Transformations

Here’s how you can change the node’s offset, rotation and scale:

var node = ...; // scene.root.children[0];
node.translation = vec3(10, 20, 30);
node.rotation = vec3(0, 0, 90);
node.scale = vec3(1.2, 1.2, 1.2);

Use exactly the same values as you enter to the transformation page in the user interface.

Selecting Nodes

The current selection is controlled by the scene, so the approach is a bit different here. First of all you need to build a list of the node’s you’d like to select. You may use just a single node, as well.

Let’s select a very first top level node in the scene (assuming that the scene is not empty):

scene.selection = scene.root.children[0];

Easy? OK, let’s select all the top level items in the scene:

scene.selection = scene.root.children;

See the difference? We passed an array. What about removing the selection? Pass null or empty array, both work well:

scene.selection = null;
scene.selection = [];

So, this is easy. What if you need to add to the current selection? It’s all about array manipulation. Let’s add a very first top level node to the current selection:

var sel = scene.selection;
sel.push(scene.root.children[0]);
scene.selection = sel;

The second line is a javascript-way to append an element to array.

Rearranging Nodes

You can do this easily using the mouse, you can do this using script, as well. Boxshot allows you to get a list of nodes and make them then children of another one at a specific position. This includes re-parenting, so useful for grouping and ungrouping nodes. Here is the code that gets the current selection and drags it inside the very first node at the top level. Please make sure that you haven’t selected that node, as you will get an error message in that case.

var sel = scene.selection;
var target = scene.root.children[0];
scene.drag(target, target.children.length, sel);

The script is quite straightforward, the main job is done in the last line. The first parameter of the drag() method is the target node, the second is a position (we pass the number of target’s children there to add to the end), and the last one is a list of nodes to drag.

Cloning Nodes

This is useful when you created a complex mesh with all the parameters and materials adjusted and need to create a similar one to put beside. Boxshot allows you to clone just the node, or its children, as well. The code is simple:

var n = scene.root.addMesh("sphere", "generator.simple.sphere");
n.generator.radius = 1;
n.translation = vec3(0, 0, 1);
var n1 = scene.clone(n, false);
n1.translation = vec3(0, 0, 10);

Please note that you can’t clone the root node, and the following code will return error:

scene.clone(scene.root);

That’s because the root node has no parent, so there is no place to attach a clone. If you need to clone all the top level items, please consider moving them inside the group node first and then clone it instead:

var top = scene.root.children;
var g = scene.root.addGroup("group");
scene.drag(g, 0, top);
var g1 = scene.clone(g, true);
g1.name = "cloned group";


 

Deleting Objects

After all these traversing and editing, it is very easy to delete nodes. Simply make a list of nodes or a single node, and pass it to the appropriate method of the scene object. The script below deletes all the selected nodes:

scene.del(scene.selection);

Another script, deletes a first top level node in the scene:

scene.del(scene.root.children[0]);

You can’t delete the root node, so you’ll get an error if you try the following code:

scene.del(scene.root);

That’s all you need to know about the deletion.

More Scripting Tutorials