This tool lets you run Python scripts in Smode.
defines when the script is executed. By default it is set to "Manual".
The options are:
: when the
trigger is pressed
: at script preload, for instance when the project is loading
: at script activation and reactivation
At Parameter Change
: when a parameter of the script changes
At Every Update
: every frame
: at script deactivation
: at script unload, for instance when the project is closing
The output Console of Smode is also refreshed by the execution of the code. When in the text editor, type Ctrl+Enter to compile and execute the script.
When you change the code of your script you need to recompile it by typing Ctrl+Enter
Import and Export your Script
To import and export your Script simply drag and drop it from and to your media directory.
Oil and SmodeSDK objects
In addition to regular Python and imported modules, all Oil and SmodeSDK objects can be instanciated.
Oil is a library upon which Smode is based, that re-implements various C++ types so that their variables can be introspected. There are atomics (Integer, Boolean ...), smart pointers, containers and so on. SmodeSDK implements classes relevant to graphics and show, such as Textures for instance. Both are automatically imported in every script. Use the Python built-in
in the script to query all native objects.
For instance, Integer is one of them and you can write
myInt = Oil.Integer(4)
to construct one with an initial value.
Most types in Oil / SmodeSDK don't have a Python binding yet (and don't need one), but can still be constucted by passing their name to the
method. For instance
, which is an Oil type without a Python binding.
Oil types that currently have a useful binding and can be constructed are:
, constructed with an optional bool argument
, constructed with an optional int argument
, constructed with an optional float argument
, constructed with an optional string argument
, constructed with optional named arguments, such as "red", "green", "blue" and "alpha"
, constructed without arguments but can be filled with append and insert methods
Pointer types, while having a binding, are better created with the Oil.createObject method
Here are a few other useful Oil types, without a binding but that can be constructed with the Oil.createObject mechanism:
"owns" an instance in the script.
creates a dropdown menu that lets you instanciate one of the numerous classes inheriting from Number: Angle, RelativeTime etc.
references to an instance of the provided type or its descendents. If the pointed type is abstract (ex:
, or with a Layer), it will create a dropdown menu that lists all concrete instances in the project. If it's concrete, it is possible to drag and drop an element of this class there.
for a position in 3D space
for an orientation
for a scale
To access the pointed Oil object, use the get() method of the pointer.
SmodeSDK types that currently have a useful binding and can be constructed are:
, constructed without arguments
, constructed with optional named arguments
Types with bindings can be accessed and set with the = operator; for the other ones you will need to use the get() and set() to convert properly with Python types. For types whose constructors accept optional named arguments, such as Color, any argument accessible trough print(dir()) can be set this way. Ex:
myColor = Oil.Color(red=1., blue=0.5)
To expose parameters in the Tool, start the script with your variables declarations as follows (one per line): the name of the variable, followed by a colon, and the constructor of the object. For instance, the following code will display a widget for an Integer and a selector of cameras of the project:
(remaining of the script...)
All variables exposed by the script are accessible as children properties of the
object. Following the previous example, the first exposed variable can be accessed by
. Beware: this is an instance of Oil.Integer, you need to call the get() method to retrieve a Python int.
For any object, you can access a variable by its name(
), or iterate through them with the methods
(that takes the index as a parameter).
Navigate through elementTree
The root of the tree is accessed by
. As usual,
will display all variables. The ones in the plural form are usually an array of Element children:
. They themselves can have children arrays, and it's possible to iterate upon them.
Beware that rootElement is different in different Element trees: if the script is located in the Stage it will be a RootStageElement, in the Show it will be a Scene, and so on.
The script.document will return the file (project or compo) you are currently working in. There are a lot of interesting properties that can be accessed; once again use print(dir()) to list them. For instance you can get the Stage with
The following properties can be used to navigate more precisely starting from any Element:
returns the object that owns the caller; for instance an array
same, but the returned object is an Element (for instance, since an array is not an Element, it will probably fallback to be the owner of the array)
some Elements are hidden in the Element tree (Placements for instance). This returns the first Element that is present in the tree.
In order to create layers, you need the name of its generator class; check the layers Class names
list for information.
Example with a simple 2d compo layer
Instantiate your layer
Define the type
Place it in the Element tree
myLayer = SmodeSDK.TextureLayer(generator=SmodeSDK.Compo())
Get and set parameters for a layer
Following the previous example, the newly created layer could be accessed by:
myLayer = script.rootElement.layers[len(script.rootElement.layers) - 1]]
Now using the usual print(dir(myLayer)) method, we can see a few properties of interest:
myLayer.label = "myLayer" # will rename the layer in the element Tree
myLayer.activation.set(False) # will deactivate the layer
The first layer named "myLayer" could also be retrieved with:
myLayer = script.rootElement.layers["myLayer"]
It is also possible to drag and drop an Element from the ElementTree directly in the script. The path to this Element will be automatically pasted, but beware that this is a harcoded path. Also, it works if the script is in the same tree. If you want to have a link robust to path changes, you can expose a WeakPointer to a concrete class at the beginning of the script and drag the Element on it. For instance for a Layer: myPointer:
Here is an example of a simple 3d layer with a box and an additional modifier:
box = Oil.createObject("BoxGeometryGenerator")
modifier = Oil.createObject("ColorizeGeometryModifier")
renderer = Oil.createObject("SurfaceGeometryRenderer")
myLayer = Oil.createObject("GeometryLayer")
myLayer.generator = box
myLayer.renderer = renderer
Here is an example of a shape layer drawing a simple circle:
circle = Oil.createObject("CircleShapeGenerator")
renderer = Oil.createObject("DefaultShapeRenderer")
layer = Oil.createObject("ShapeLayer")
layer.generator = circle
layer.renderer = renderer
Install Python modules
It is possible to install and use Python modules locally in Smode. The easiest way is to use pip. First, go to you Smode folder, thent in the
subfolder and try to run
. If you get the error that a .dll is missing, copy here the
located in the parent Smode folder.
Then open a command line tool at this specific location and run
python.exe -E -m pip install
+ the name of your module. It will be downloaded and installed in the local Smode/python directory, and you can import it in the scripts.