Skip to main content

Scripts

Tellusim Engine uses C++ as its default scripting language. It supports dynamic recompilation during development via hot-loading. Script performance is equivalent to that of native C++.

There are three scene types where users can assign custom script files:

info

Visual scripting can be performed using the Script Flow plugin, which is integrated in the Tellusim Explorer.

info

Scripts have full access to the Tellusim API and can use any C++ or C-compatible library.

Script layouts

Scripts are standard C++ files with additional layout() annotations used to define parameters. These parameters are automatically exposed in the editor.

Each script must include a layout declaration that defines the class name used for instantiation:

layout(instance = MyClass);

Scripts support all basic parameter types, including scalars, vectors, matrices, colors, and strings. Any parameter type can be passed using raw pointers, and scripts have native access to all custom C++ code.

The script below demonstrates the declaration of all supported parameter types:

// Declare a signed integer parameter with a checkbox editor
layout(bool) int32_t signed_integer = 1;

// Declare unsigned integer parameter with slider range
layout(min = 1, max = 8) uint32_t unsigned_integer = 1 + 2;

// Declare floating-point parameter with maximum slider value
layout(max = 2.0f) float32_t linear_scalar = 2.0f * 3.0f;

// Declare logarithmic floating-point parameter
layout(base = 2.0f) float32_t log_scalar = 1.0f;

// Declare vector parameter with value assigned via a setter method and two-digit precision slider
layout(set = set_vector_2, digits = 2) Vector2f vector_2 = Vector2f(0.0f);

// Declare vector parameter with uniform range
layout(min = 1.0f, max = 2.0f) Vector3f vector_3 = Vector3f(1.0f, 2.0f, 3.0f);

// Declare vector parameter with non-uniform range
layout(min = 1.0f, max = 3.0f, max_w = 2.0f) Vector4f vector_4 = Vector4f(1.0f, 2.0f, 3.0f, 4.0f) * 2.0f;

// Declare linear color parameter
layout(linear) Color color = Color(0.1f);

// Declare vector parameter with linear color editor
layout(color, linear) Vector4f vector = Vector4f(0.1f, 0.1f, 0.1f, 1.0f);

// Declare matrix parameters with direct assignment
layout() Matrix3x2f matrix_3x2 = Matrix3x2f::translate(1.0f, 2.0f);
layout() Matrix4x3f matrix_4x3 = Matrix4x3f::scale(1.0f, 2.0f, 3.0f) * Matrix4x3f::rotateX(90.0f);
layout(spacer) Matrix4x4f matrix_4x4 = Matrix4x4f::perspective(60.0f, 1.0f, 0.1f);

// Declare string parameter with a value assigned via a setter method
layout(set = set_string) String string = "example value";
info

A set method is used to assign the parameter value during script initialization and on changes. Otherwise, a variable with the same name must exist within the class.

info

min, max, bool, color, linear, and spacer layout arguments are used as editor hints.

info

Numerical values are resolved using the Expression namespace.

Script compilation

Script compilation is handled internally by the engine and is fully transparent to the user.

By default, compiled scripts are stored in the scripts.x64 or scripts.arm64 directory. These directories can be safely deleted - any missing scripts will be recompiled automatically when needed.

Additional script dependencies can be specified using the following #pragma directives:

  • #pragma cflags(flags) - passes flags to the compiler using Unix-style syntax
  • #pragma ldflags(flags) - passes flags to the linker
  • #pragma include(path) - add an include directory
  • #pragma library(name) - link an additional library
info

The ROOT keyword can be used to specify the path to the Engine root directory for include and library parameters.

info

The ARCH keyword can be used in the library parameter to specify a platform-dependent architecture (windows/x64, windows/arm64, linux/x64, linux/arm64, macos/x64, macos/arm64).

info

All scene and project scripts can be exported as a single or multiple *.cpp files and embedded into the binary.

Examples

Node Rotation Script

This script demonstrates basic node rotation using three independent rotation axes:

#include <scene/TellusimScene.h>
#include <scene/TellusimGraph.h>
#include <scene/TellusimNodes.h>
#include <scene/TellusimObjects.h>

using namespace Tellusim;

layout(instance = RotationScript);
layout(min = -32.0f, max = 32.0f) Vector3f rotation_speed = Vector3f(0.0f);

/*
*/
class RotationScript : public NodeScript {

public:

RotationScript(void *ptr) : NodeScript(ptr) { }

virtual void update() {

// Update rotation angle
float32_t ifps = (float32_t)getScene().getIFps();
rotation_angle += rotation_speed * ifps;

// Get parent node
Node parent_node = getParent();
if(parent_node && parent_node.isObject()) {

// Rotate parent pivot matrix
NodeObject node_object = NodeObject(parent_node);
node_object.setPivotTransform(Matrix4x3f(Quaternionf::rotateZYX(rotation_angle.x, rotation_angle.y, rotation_angle.z)));
node_object.updateScene();
}
}

Vector3f rotation_speed = Vector3f::zero; // rotation speed
Vector3f rotation_angle = Vector3f::zero; // rotation angle
};

Physics Plugin Script

This script uses the Box2D plugin as a graph script:

info

One-frame delay is intentional for finalizing Engine objects.

note

The plugin source is directly included in the script.

#include <physics/box2d/source/TellusimBox2D.cpp>
#pragma library(ROOT/plugins/physics/box2d/extern/lib/ARCH/box2d)

using namespace Tellusim;

layout(instance = GraphPhysicsBox2D);
layout(min = 20.0f, max = 500.0f, set = set_fps) float32_t fps = 60.0f;
layout(min = -20.0f, max = 20.0f, set = set_gravity, spacer) Vector2f gravity = Vector2f(0.0f, -9.81f);

/*
*/
class GraphPhysicsBox2D : public GraphScript {

public:

GraphPhysicsBox2D(void *ptr) : GraphScript(ptr) {
physics = makeAutoPtr(new Box2D());
}

virtual void update() {
if(initialized && physics) {
Scene scene = getScene();
physics->update(ifps);
physics->update(scene);
}
}

virtual void dispatch() {
if(!initialized && physics) {
Scene scene = getScene();
if(!physics->create(scene)) physics.clear();
initialized = true;
}
}

void set_fps(float32_t fps) {
ifps = 1.0f / max(fps, 20.0f);
}
void set_gravity(const Vector2f &gravity) {
if(physics) physics->setGravity(gravity);
}

private:

AutoPtr<Box2D> physics;
bool initialized = false;
float32_t ifps = 1.0f / 60.0f;
};