Skip to content

Lua Binding

Kigs-framework edited this page Mar 1, 2023 · 4 revisions

Table of Contents

Lua (5.3.5) programming language is embedded in the framework here :

https://github.com/Kigs-framework/kigs/tree/master/libs/cross_platform/lua

With minor changes for Universal Windows Platform build.

The same directory also contains LuaIntf : A binding between C++11 and Lua language :

https://github.com/SteveKChiu/lua-intf

To learn more about Lua, look here : https://www.lua.org.

Binded Framework Classes and Methods

Here is the list of binded classes and their accessible methods from Lua :

  • CoreModifiable :

    • name() : return instance name
    • addItem(CMSP item) : add a CoreModifiable instance smart pointer (CMSP) to another (see CoreModifiable page)
    • removeItem(CMSP item) : remove an instance smart pointer (CMSP) from another (see CoreModifiable page)
    • aggregateWith(CMSP item) : aggregate a CoreModifiable instance smart pointer (CMSP) to another (see CoreModifiable page)
    • removeAggregateWith(CMSP item) : remove an aggregate (see CoreModifiable page)
    • parents() : get parents list
    • childs() or items() : get children list
    • getSonsByType(type) : get list of children of given type
    • getSonsByName(name) : get list of children with given name
    • init() : call CoreModifiable Init
    • uid() : get instance unique id
    • type() : get instance exact type
    • isSubType(type) : check if instance is of the given type
    • addAttribute(val) : add a dynamic attribute of the type of the given val (bool, float, string or vector)
    • onEvent(method_name or lua function,notification_name) : add an observer on notification_name to call method_name or directly lua function.
    • getByPath(path) : search an instance by path
    • importAsSon(filename) : import the given file and add CoreModifiable tree to calling CoreModifiable instance
    • emit(signal_name) : emit a signal with given name
  • CMSP :

    • get() : get CoreModifiable instance pointed by the smart pointer
  • v2f, v3f and v4f : 2D, 3D or 4D vectors

    • Dot(v1,v2) : static method, return dot product of v1 and v2
    • Cross(v1,v2) : static method, return cross product of v1 and v2 (not available on v4f)
    • Norm(v1) : static method, return norm of v1
    • NormSquare(v1) : static method, return squared norm of v1
    • normalize() : normalize vector
    • normalized() : return a copy of the normalized vector
    • copy() : return a copy of the vector
    • members can be accessed with .x, .y, .z (for v3f and v4f), .w (for v4f)
    • vector standard operation : * + - / are also available
  • mat3x4 : 3 x 4 matrix (3D transform matrix)

    • setRotationX(angle) : set current matrix to be a X axis rotation matrix of given angle
    • setRotationY(angle) : set current matrix to be a Y axis rotation matrix of given angle
    • setRotationZ(angle) : set current matrix to be a Z axis rotation matrix of given angle
    • preRotateX(angle) : pre rotate current matrix around X axis with given angle
    • preRotateY(angle) : pre rotate current matrix around Y axis with given angle
    • preRotateZ(angle) : pre rotate current matrix around Z axis with given angle
    • postRotateX(angle) : post rotate current matrix around X axis with given angle
    • postRotateY(angle) : post rotate current matrix around Y axis with given angle
    • postRotateZ(angle) : post rotate current matrix around Z axis with given angle
    • setScale(sx,sy,sz) : set current matrix to be a scale matrix with given scale on each axis
    • preScale(sx,sy,sz) : pre scale current matrix with given scale on each axis
    • postScale(sx,sy,sz) : post scale current matrix with given scale on each axis
    • setTranslation(v) : set current matrix to be a translation matrix of given v3f vector
    • preTranslate(v) : pre translate current matrix with given v3f vector
    • postTranslate(v) : post translate current matrix with given v3f vector
    • setRotationXYZ(aX,aY,aZ) : set current matrix to be a rotation matrix with angles aX, aY, aZ. Rotations are applied in order X, then Y, then Z
    • setRotationZYX(aX,aY,aZ) : set current matrix to be a rotation matrix with angles aX, aY, aZ. Rotations are applied in order Z, then Y, then X
    • preRotateXYZ(aX,aY,aZ) : pre rotate current matrix (Rotations are applied in order X, then Y, then Z)
    • preRotateZYX(aX,aY,aZ) : pre rotate current matrix (Rotations are applied in order Z, then Y, then X)
    • postRotateXYZ(aX,aY,aZ) : post rotate current matrix (Rotations are applied in order X, then Y, then Z)
    • postRotateZYX(aX,aY,aZ) : post rotate current matrix (Rotations are applied in order Z, then Y, then X)
    • setIdentity() : set matrix to identity
    • setNull() : set each matrix member to 0
    • isIdentity() : return true if matrix is identity
    • transformPoint(v) : transform given v3f vector as a point with current matrix (apply translation)
    • transformPoints(list_of_v) : transform each v3f vector in the given list as a point with current matrix (apply translation)
    • transformVector(v) : transform given v3f vector with current matrix (translation is not applied)
    • transformVectors(list_of_v) : transform each v3f vector in the given list with current matrix (translation is not applied)
    • copy() : return a copy of the current matrix
  • core :

    • ByName(name) : returns the list of CoreModifiable with the given name
    • ByType(type) : returns the list of CoreModifiable with the given type
    • GetFirstInstanceByName(name) : returns the first CoreModifiable found with the given name
    • GetModule(name) : returns the module (CoreModifiable) with the given name
    • PostNotification(name,sender,data) : post notification with the given name. sender and data are optional CoreModifiable parameters
    • AddAutoUpdate(instance) : add given CoreModifiable instance to auto update mechanism
    • RemoveAutoUpdate(instance) : remove given CoreModifiable instance from auto update mechanism
    • SID(string) : return KigsID (unsigned int) for the given string
    • Connect(sender,signal,receiver,slot) : Connect CoreModifiable sender's signal to CoreModifiable receiver slot
    • Disconnect(sender,signal,receiver,slot) : Disconnect CoreModifiable sender's signal to CoreModifiable receiver slot
    • Import(filename) : Import filename as CoreModifiable tree and returns CMSP root

Accessing Kigs Framework from Lua

On Lua side, generic functionalities of the framework are available :

-- create an UIImage instance named logo (get a smart pointer)
local logoSP = CoreModifiable("logo","UIImage")
local logo=logoSP:get()
-- set CoreModifiable attributes directly
logo.Texture = "KigsHD.png"
logo.Dock = {0.5,0.5}
logo.Anchor = {0.5,0.5}
logo.Priority = 10
-- and init logo
logo:init()

CoreModifiable attributes are accessed directly by their name preceded by a dot '.'.

local rotate = logo.RotationAngle
rotate = rotate + 0.1
logo.RotationAngle = rotate

Binded methods or CoreModifiable methods are accessed the classic Lua way with a ':' ( except for static methods, were '.' should be used ) :

-- call CoreModifiable method "HelloFromLua" defined on target object 
target:HelloFromLua()

Accessing Lua from Kigs Framework

Executing Lua Code

It's possible to just execute some Lua code from a file in C++ :

auto lua = KigsCore::GetModule<LuaKigsBindModule>();
bool result=lua->ExecuteLuaFile("myCode.lua");

Or to execute some code when importing an XML file by adding a "Lua" item to an instance :

<Lua N="someCode">
-- code is executed when XML file is imported
   local panel=core.GetFirstInstanceByName("panel")
   panel.Color={1.0,0.0,0.0}
</Lua>

or

<Lua N="someCode" V="#someCode.lua"/>

Add Lua Method to an Instance

In XML it's also possible to add a Lua function (as a CoreModifiable method) to a CoreModifiable instance :

<Lua N="Click">
   -- here self is the current CoreModifiable
   return function(self)
      local currentColor=self.Color
      self.Color={1.0-currentColor.x,0.0,0.0}
   end
</Lua>

LuaBehaviour Class

The LuaBehaviour class is used to add functionality to an instance using the Lua language.

Serialization

The easy way to do it, is to add this kind of item directly in XML to the targeted instance :

<Inst N="testLua" T="LuaBehaviour" Aggregate="true">
	<Attr N="Script" V="#test.lua"/>
</Inst>

The LuaBehaviour must be added as an aggregate to its parent instance.

Here, the "Script" attribute value is "#test.lua". The starting '#' indicates a filename to load. So here, the "test.lua" file is loaded (if found) and its content is interpreted as Lua.

The code can also be embedded into the XML file as CDATA:

<Inst N="testLua" T="LuaBehaviour" Aggregate="true">
   <Attr N="Script">
   <![CDATA[
local Sample7Script = {} 
Sample7Script.logo=0

function Sample7Script:init()
  local logoSP = CoreModifiable("logo","UIImage")
  self.logo=logoSP:get()
  self.logo.Texture = "KigsHD.png"
  self.logo.Dock = {0.5,0.5}
  self.logo.Anchor = {0.5,0.5}
  self.logo.Priority = 10
	
  self.target:addItem(logoSP)

  self.logo:init()
end

return Sample7Script
  ]]>
  </Attr>
</Inst>

In C++ Code

Of course, LuaBehaviour instance can be created using framework code, the "classic" way :

CMSP behaviour = KigsCore::GetInstanceOf("behaviour", "LuaBehaviour");
behaviour->setValue("Script", "#ScriptOnApp.lua");
// aggregate LuaBehaviour with this
aggregateWith(behaviour);
behaviour->Init();

Lua Side Syntax

Behaviour Code

Lua code must have the following form :

-- you can call it whatever you want
local behaviourObjectName = { var1 = 0; var2 = "two" } 

-- Insert methods here
function behaviourObjectName:doSomething(param1)
	self.var1 = param1
end

return behaviourObjectName 

The methods "init()", "update(current_time)", "destroy()", "addItem(other)", "removeItem(other)" are called automatically when aggregate is initialized, update...

Adding a CoreModifiable Lua method directly in Lua is possible using WRAP_METHODS table in the object declaration :

-- reset is wrapped so C++ can call directly the reset method on target object
local Sample7Script = { logo=0; startingTime=0; WRAP_METHODS = {"reset"}; }

-- the reset method 
function Sample7Script:reset(current_time)
   self.startingTime = current_time
end

Or directly by adding a Lua function to the target object in init function :

function Sample7Script:init()
   -- add reset function to target  
   self.target.reset = function (current_time)
	self.startingTime = current_time
   end
end

So on the C++ side the Lua reset method can be called like another CoreModifiable method :

// instance is the object aggregated with LuaBehaviour 
instance->SimpleCall("reset",GetApplicationTimer()->GetTime());

Accessing CoreModifiable Instance from LuaBehaviour

LuaBehaviour functions can use self.target to access the CoreModifiable instance aggregated to LuaBehaviour :

-- create an UIImage instance named logo (get a smart pointer)
local logoSP = CoreModifiable("logo","UIImage")
-- then add logo (smart pointer) to target
self.target:addItem(logoSP)

LuaImporter Class

It's also possible to import CoreModifiable trees created in Lua using LuaImporter class.

In XML add the following item to import scene.lua and add it in the current XML hierarchy:

<Inst N="lua" T="LuaImporter">
   <Attr N="Script" V="scene.lua"/>
</Inst>

The syntax of a lua file aimed at import looks like that :

local result = 
{
   item("itemName1", "itemType1", {attributeName1=0,... }).items(
      item("itemName2", "itemType2", { attributeName1=true, ... } ),
      item("itemName3", "itemType3", { attributeName1=32, ... } ),
      ...
   )
}
return result

"item" keyword create a CoreModifiable instance. First two parameters are instance name and instance type, then the list of attributes to initialize with given value.

To add sons to an item, use the ".items" keyword.

In the previous example, itemName2 and itemName3 are sons of itemName1.

As it's Lua code, it's possible to define functions and call them as helpers to create objects with the same type or initialize attributes :

local specialNode3D = function(name)
	return item(name, "Node3D", {Show=false, IgnoreBBox=true, CollideMask=0}).items(
		item("nodepth", "RenderingCustomizer", {OverrideDepthTest=0, RenderPassMask=16})	
	)
end
local result = 
{
   specialNode3D("node1").items(
      specialNode3D("node2"),
      specialNode3D("node3")
   )
}
return result

It's also possible to import an item from another XML or Lua file :

local result = 
{
   item("itemName1", "itemType1", {Param1=-1, Param2=-1}).items(
      xml("item2FromXML", "item2.xml",{Param1 = 5}),
      lua("item3FromExternLua", "item3.lua"),
   )
}
return result

Or to reference an already loaded item with the "ref" keyword :

    item("itemName1", "itemType1", {Param1=-1, Param2=-1}).items(
      ref("refName", "refType")
   )

And finally, it's also possible to connect a signal and slot :

item("button", "UIButtonImage", {Priority=10, UpTexture="Up.png", DownTexture="Down.png",Dock={0.9,0.1}}).items(
      connect("this","ClickUp" ,"../UIItem:panel","Click")
   )

And to add an instance to AutoUpdate mechanism :

item("itemName1", "itemType1", {attributeName1=0,... }).items(core.AddAutoUpdate)

Find all the sample code from this wiki section in Sample7 project (browse the code)