Scripts can be used to extend the behavior of nodes and scenes.

This page documents the current embedded scripting workflow centered on SceneLuaVM. Harfang also ships a public Squirrel runtime package for host-side scripting through hg_squirrel, but embedded scene scripting remains Lua-oriented for now.

Host vs. Embedded VM

When using Harfang from a scripting language it can be difficult to differentiate between parts of your program running on you main script VM and parts of your program running on one of the supported embedded VMs.

We differentiate between those VMs by using the term host VM and embedded VM. For example, you may write a program in CPython, Lua or Squirrel and declare a scene extended using Lua scripts. In that case, the language running your application is the host VM and Lua is the embedded VM.

Declaring Scripts

Create a Script component and assign it to a node or scene using Node.SetScript or Scene.SetScript. Set the path to the script source using Script.SetPath.

Creating & Evaluating Scripts

Create a backend such as SceneLuaVM and call SceneLuaVM.SceneCreateScriptsFromAssets to create the script states corresponding to the scene declaration. A Script component can be assigned to multiple nodes in which case they will all share the same execution environment.

You should then use the SceneUpdateSystems function to update both the scene and its systems. This function will update all the systems you pass to it and implement a default behavior that dispatch common events to script using a set of specific callbacks.

Script Environment

The following symbols are defined when creating the environment for a script.

Symbol Description
G Table shared by all script component created by the same scene.
hg Access to the Harfang API.
scene Scene object this component belongs to.

Default Events & Callbacks

Node events reported by the default update behavior:

Scene events reported by the default update behavior:

Communicating with Scripts

Depending on the host and embedded VM used you may be able to access a script component environment directly (eg. SceneLuaVM.GetScriptEnv).

If this is not possible however this can be done using the backend get and set value methods from any host VM. In some cases the transfer will be automatic while in other cases you may need to explicitely marshall the outgoing/incoming values.

Source VM/Target VM CPython Lua
CPython N/A LuaObject.Pack/LuaObject.Unpack
Lua N/A -

Sending a value from a host CPython VM to an embedded Lua VM and back.

# from host Python to embedded Lua
lua_vm.SetScriptValue('target_node', lua_vm.MakeLuaObject().Pack(node))

# from embedded Lua to host Python
target_node = lua_vm.GetScriptValue('target_node').Unpack()

Sending a value from a host Lua VM to an embedded Lua VM and back.

-- from host Lua to embedded Lua
lua_vm.SetScriptValue('target_node', node)

-- from embedded Lua to host Lua
node = lua_vm.GetScriptValue('target_node')

Keeping the System Synchronized

Call the script system garbage collect method (eg. SceneLuaVM.GarbageCollect) on each update to ensure that destroyed nodes or components are properly removed. If you know that no node or component was destroyed during a particular update, not calling the garbage collector will save on performance.