Scripting with Python in DELTAGEN: Working with the Scene tree

In the third post of this series, we have a deeper look how to write scripts using the Scene tree. First, it requires some basics to understand the structure of the Scene tree and the approach to access its items. Then, we focus on a practical example and how to run “semi-automatic” scripts.

Scene tree foundations

A tree is a well-known data structure in computer science. It consists of a root element and an arbitrary amount of children. Some children can act as root element for other items in the tree. Others are leaf nodes, which cannot have any children. Finally, you get a nested hierarchy of elements. Formats like XML or JSON follow the same structure.

Let us have a look at the Teapot example shipped with DELTAGEN to understand the above-mentioned terms:

What is the root element? It is the selected model node, which is called “Teapot.3xf”. Its only child item is the body “Teapot”, which acts as parent for the Shell “shell_teapot”. Accordingly, the shell is the parent of the four faces. These are the leaf nodes in the tree.

Typically, you want to run a script, which “visits” all items of a certain type, name, metadata etc. and applies an operation to it.  The following snippet exactly does that for shapes:

Let us analyze the script starting at the bottom (line 19): We check the global variable ACTIVE_ SCENE if we currently have an active scene.  If that is the case, we retrieve the contained models. By default, a scene contains exactly one model, but you might have multiple when the XPlore module is loaded. Afterwards we call a helper function traverseTree passing the first model as parameter.

The functions expects as argument on object of type Group. Group is a base class, from which all types inherit, which can have children. The following diagram shows all classes inheriting from Group:

Now it is clear, why we were able to pass the Model to the function: It inherits from File, which is a child class of Group.

In line 8 we loop over all children. For all types exposed in DELTAGEN there is a helper function to figure out if an object inherits from a class. E.g. Objects.isShape() returns True if the object is a Shape. In order to access its special methods you need to convert with Objects.toShape(). Starting from line 11 the actual code can be added to modify the shape.

Finally, we need to ensure, that also subgroups are correctly processed. Therefore, the “if clause” in line 14 is used: We check if the child is a Group and pass it to the traverseTree function. This recursive approach is typical if you want to traverse a tree data structure. 


Sorting the elements of a group alphabetically

With the above knowledge, we can now write a script, which enables us to order the elements of the current selection alphabetically.

As a first step, we write a loop accessing all elements of the selection. Like in the example before we call a helper function named sortChildren, which can call itself afterwards:

If the passed parameter is a group, we need to sort its children. Therefore, we retrieve all children and add them to a dictionary. Since we need to insert the scene elements in a different order afterwards, we temporarily remove them from the group:

The purpose of the dictionary is to lookup the scene objects by their names. This is needed, because we require a sorted list of the names. This we achieve by getting all keys and passing them to a built-in sort function:

Finally, we only need to add the scene elements in the order given by the sorted key list. In order to know, which scene object belongs to a name we utilize the previously populated dictionary:

Now only the code is missing to sort the contained groups. This is done by calling sortChildren recursively like in our previous example:

This script has two limitations: It does not work if a group contains children having the same name. With a dictionary maintaining a list of objects per name, it would be possible as well. In order to keep the example smart and simple we decided to ignore this special case. In addition sorting a group containing lights, might change the visual appearance. Hence, the script should only be applied if the selected element only contains subgroups and geometries.  

The picture below shows the complete script:


Semi-automatic scripts

In DELTAGEN you can access the current selection in the scene tree. This allows doing modifications by selecting an object, running a script, selecting a different object and running the script again. By assigning shortcuts to your favorite scripts, this process can be even more accelerated.  Therefore, select your script, open the context menu and select the menu item “Define shortcut”:

Now you can also close the script editor while triggering the scripts by your custom shortcuts.


Final notes

The complete scripts are attached to this post as well. They can be directly executed with DELTAGEN 2022x RF1. With DELTAGEN 2022x the call to removeChild in the sort script is not functional.  All other snippets  work as expected.

 DELTAGEN ​​​​​​​​​​​​​​PYTHON ​​​​​​​SCRIPTING