Using Lua

Kanzi Engine Lua API is a platform-independent interface to the Kanzi Engine using the Lua programming language. It allows you to create application and user interface logic in Kanzi Studio.

When you export a kzb file, Kanzi Studio embeds Lua scripts in the kzb file.

Note

To use Kanzi Engine Lua API on platforms that do not support runtime loading of dynamic libraries, such as Android, add to the CMakeLists of your application the link to the kzlua library:

if(ANDROID)
   target_link_libraries(Application_Name Kanzi::kzlua)
Copy to clipboard

This topic provides an overview of the fundamentals of Kanzi Engine Lua API. For complete API reference, see Kanzi Lua API reference.

Learn how to develop application logic for your Kanzi applications using Kanzi Engine Lua API by completing the Tutorial: Kanzi Engine Lua API basic use.

Kanzi uses Lua 5.4. See https://www.lua.org/manual/5.4/.

Executing a Lua script

To execute a Lua script:

  1. In the Node Tree or Prefabs, select or create a node. In the Node Components > Triggers, create a trigger where you want to execute the Lua script.

    For example, from the Asset Packages drag the Button asset to the Preview and in the Prefabs, use the Button: Click trigger.

    ../../_images/node-tree-prefabs-fc-button.png ../../_images/node-components-button-click1.png
  2. In the Node Components > Triggers, press Alt and right-click the trigger where you want to execute the Lua script and select Run Lua Script.

    For example, in the Prefabs select the Button. In the Node Components, press Alt and right-click Button: Click and select Run Lua Script.

    ../../_images/node-components-button-click-run-lua-script.png
  3. In the Run Lua Script action set the Lua Script property to + Script File and name the script.

    Kanzi Studio creates Lua scripts in the Library > Resource Files > Scripts.

    ../../_images/node-components-run-lua-script-script-file.png ../../_images/create-script-my-script.png
  4. In the Library > Resource Files > Scripts double-click the script that you created. In the Script Editor add the Lua code and click Save.

    print("Hello world!")
    
    Copy to clipboard
    ../../_images/library-scripts-my-script.png ../../_images/script-editor-my-script.png

When you set off the trigger, it executes the Run Lua Script action, which runs the code in the script. For example, when you click the button, the Lua script prints Hello world! to the Log.

../../_images/preview-button-lua-hello-world.gif

Using Lua variables

In Lua, you can declare:

  • Local variables, which are accessible only in the scope of the script where you declare a variable

    Kanzi destroys local variables at the end of the scope.

    local x = 1
    
    Copy to clipboard
  • Global variables, which are accessible in all scripts and are persistent across multiple script executions

    if runCount == nil then
        -- Initialize a persistent global variable `runCount` on the first run of this script.
        runCount = 0
    end
    runCount = runCount + 1
    print("This script has been executed " .. runCount .. " times.")
    
    Copy to clipboard

Accessing nodes

When you set off a trigger that executes the Run Lua Script action, the action assigns to the contextNode variable the reference to the node that contains the trigger.

-- Print the name of the node that executes the script.
local name = contextNode:getProperty(Node.NameProperty)
print(name)
Copy to clipboard

To navigate the node tree, start with the contextNode variable, then use the lookupNode function with:

  • Relative path

    -- To access the parent node.
    local parent = contextNode:lookupNode("..")
    local parentName = parent:getProperty(Node.NameProperty)
    print(parentName)
    
    Copy to clipboard
    -- To access a child node with the name "Empty Node 2D".
    local child = contextNode:lookupNode("Empty Node 2D")
    local childName = child:getProperty(Node.NameProperty)
    print(childName)
    
    Copy to clipboard
  • Alias in the nearest resource dictionary

    -- To access a node to which the alias "Home" in the nearest resource dictionary points.
    local node = contextNode:lookupNode("#Home")
    local nodeName = node:getProperty(Node.NameProperty)
    print(nodeName)
    
    Copy to clipboard

To access all child nodes of a node, use the getChild and getChildCount functions.

local childCount = contextNode:getChildCount()
for i = 0, childCount - 1 do
    local child = contextNode:getChild(i)
    local name = child:getProperty(Node.NameProperty)
    print(name)
end
Copy to clipboard

Using properties

Kanzi Engine Lua API allows you to work with the existing property types. Most Kanzi property types are present in Kanzi Engine Lua API.

To access property types, use their full Kanzi Engine names, such as Node.OpacityProperty. You can find the full Kanzi Engine names for all property types available in Kanzi Engine Lua API in Kanzi Lua API reference.

To access the built-in Kanzi property types:

-- Set property.
contextNode:setProperty(Node.OpacityProperty, 0.5)

-- Get property.
local opacity = contextNode:getProperty(Node.OpacityProperty)
print(opacity)
Copy to clipboard

To access a custom property type, create an instance of a PropertyType with the full Kanzi Engine name of the property type.

-- Find the "MyProject.MyPropertyType" custom property type.
local customPropertyType = PropertyType:new("MyProject.MyPropertyType")
contextNode:setProperty(customPropertyType, "Hello Kanzi!")
Copy to clipboard

See Property system and Creating property types.

Tip

For most Kanzi property types, you can find the full Kanzi Engine name in the property tooltip.

../../_images/tooltip-copy-property-name1.gif

Using vector data types

In Lua scripts, you can use as value types these Kanzi math types:

  • Vector2

  • Vector3

  • Vector4

  • ColorRGBA

  • Quaternion

  • Matrix3x3

  • Matrix4x4

  • SRTValue2D

  • SRTValue3D

For example, you can:

  • Declare local variables.

    local a = Vector2(1.4, 0)
    local b = Vector3(4.5, -2.3, 0)
    local c = Vector4()
    local d = ColorRGBA(0,0,0)
    local e = Quaternion()
    local f = Matrix3x3(Vector2(1,0), Vector2(0,1), Vector2(0,0))
    local g = Matrix4x4(Vector3(1,0,0), Vector3(0,1,0), Vector3(0,0,1), Vector3(0,0,0))
    local h = SRTValue2D(Vector2(1,1), 0, Vector2(0,0))
    local i = SRTValue3D(Vector3(1,1,1), Quaternion(), Vector3(0,0,0))
    
    Copy to clipboard
  • Assign property values.

    local srt = contextNode:getProperty(Node2D.LayoutTransformationProperty)
    srt:setTranslation(Vector2(10, 0))
    contextNode:setProperty(Node2D.LayoutTransformationProperty, srt)
    
    Copy to clipboard
  • Access the fields of all vector types with zero-based indexing.

    local v = Vector3()
    v[0] = -1.1
    v[1] = 1.2
    v[2] = 2.3
    print(string.format("%.2f %.2f %.2f", v[0], v[1], v[2]))
    
    Copy to clipboard
  • Use helper functions to create transformations.

    local j = Matrix3x3.createTranslation(Vector2(10,0))
    local k = Matrix4x4.createTranslation(Vector3(10,0,0))
    local l = SRTValue2D.createTranslation(Vector2(10,0))
    local n = SRTValue2D.createRotation(3.1415)
    
    Copy to clipboard
  • Perform mathematical operations.

    local direction = Vector2(10, 10)
    local length = direction:length()
    local squaredLength = direction:squaredLength()
    local normalizedDirection = direction:normalized()
    
    Copy to clipboard
  • Use overloaded operators for the common vector operations. For example, you can add two vectors or multiply by a scalar.

    local position = Vector2(0,0)
    local direction = Vector2(10, 0)
    local rotation = Matrix3x3.createRotationInDegrees(45.0)
    local speed = 2.4
    position = position + (rotation * direction):normalized() * speed
    
    Copy to clipboard

Creating and removing nodes

To instantiate a prefab:

-- Load a prefab at kzb URL.
local prefab = contextNode:tryAcquireResource("kzb://myProject/Prefabs/MyPrefab")
-- Create a node from the prefab.
local node = prefab:instantiate("My Node")
-- Add the node to the node tree.
contextNode:addChild(node)
Copy to clipboard

To replace all child nodes of a node with a node that you create:

-- Remove all child nodes from the current node.
contextNode:removeAllChildren()

-- Create a Text Block 2D node named "My TextBlock2D",
-- set it to show "Hello", and add it to the current node.
local node = TextBlock2D:create("My TextBlock2D")
node:setProperty(TextBlock2D.TextProperty, "Hello")
contextNode:addChild(node)
Copy to clipboard

See Using node prefabs.

Using messages

You can access all message types that are already registered with Kanzi Engine. However, you cannot define a message type.

To send messages of built-in message types:

-- Create an instance of message arguments for a message that you want to send.
local arguments = ExclusiveActivityHost2D.NavigateNextMessageMessage:newMessageArguments()
-- Set the argument values.
arguments:setLoopActivityProperty(true)
-- Send the message.
contextNode:dispatchMessage(ExclusiveActivityHost2D.NavigateNextMessageMessage, arguments)
Copy to clipboard

To access a message type by name, create an instance of MessageType with the full name of the message type:

-- Access a message type and message argument.
local messageType = MessageType:new("ExclusiveActivityHostConcept.NavigateNextMessage")
local propertyType = PropertyType:new("ExclusiveActivityHostConcept.ImplicitActivityChangeRequestMessageArguments.LoopActivity")

-- Send the message.
local arguments = messageType:newMessageArguments()
arguments:setArgument(propertyType, true)
contextNode:dispatchMessage(messageType, arguments)
Copy to clipboard

See Using messages.

Receiving messages

Set up a message handler to receive messages. Create a handler function that accepts a message argument and set the function as a message handler.

To receive messages:

-- Access a message type and message argument.
local messageType = MessageType:new("MyMessage")
local propertyType = PropertyType:new("MyMessageArgument")

-- Define a message handler.
function myMessageHandler(arguments)
    local value = arguments:getArgument(propertyType)
    print("MyMessage received, argument = " .. value)
end

-- Add the message handler to the current node.
contextNode:addMessageHandler(messageType, myMessageHandler)
Copy to clipboard

See also

Kanzi Lua API reference

Tutorial: Kanzi Engine Lua API basic use

https://www.lua.org/manual/5.4/

Using triggers

Triggers reference

Actions and messages reference

Using aliases

Property system

Creating property types

Using node prefabs

Using messages