Kigs Framework Introduction (7/8) - Lua Binding






2.09/5 (3 votes)
A multi purpose, cross-platform, free and Open Source C++ framework. Lua Binding feature
Table of Contents
- Introduction
- Bound Framework's Classes and Methods
- LuaBehaviour Class
- LuaImporter Class
- Already Published in this Series
- History
Introduction
In this article, we will see how to enhance the Kigs framework, and particularly CoreModifiable
classes with Lua.
Lua (5.3.5) programming language is embedded in the framework here:
With minor changes for Universal Windows Platform build.
The same directory also contains LuaIntf: A binding between C++11 and Lua language:
To learn more about Lua, look here: https://www.lua.org.
Bound Framework Classes and Methods
Here is the list of bound classes and their accessible methods from Lua:
-
CoreModifiable
:name()
: Return instance nameaddItem(CMSP item)
: Add aCoreModifiable
instance smart pointer (CMSP
) to another (seeCoreModifiable
article)removeItem(CMSP item)
: Remove an instance smart pointer (CMSP
) from another (seeCoreModifiable
article)aggregateWith(CMSP item)
: Aggregate aCoreModifiable
instance smart pointer (CMSP
) to another (seeCoreModifiable
article)removeAggregateWith(CMSP item)
: Remove an aggregate (seeCoreModifiable
article)parents()
: Get parents listchilds()
oritems()
: Get children listgetSonsByType(type)
: Get list of children of given typegetSonsByName(name)
: Get list of children with given nameinit()
: CallCoreModifiable
Inituid()
: Get instance unique idtype()
: Get instance exact typeisSubType(type)
: Check if instance is of the given typeaddAttribute(val)
: Add a dynamic attribute of the type of the given val (bool
,float
,string
orvector
)onEvent(method_name or Lua function,notification_name)
: Add an observer onnotification_name
to callmethod_name
or directly Lua function.getByPath(path)
: Search an instance by pathimportAsSon(filename)
: Import the given file and addCoreModifiable
tree to callingCoreModifiable
instanceemit(signal_name)
: Emit a signal with given name
-
CMSP
:get()
: getCoreModifiable
instance pointed by the smart pointer
-
v2f, v3f and v4f
: 2D, 3D or 4D vectorsDot(v1,v2)
: static method, return dot product of v1 and v2Cross(v1,v2)
: static method, return cross product of v1 and v2 (not available on v4f)Norm(v1)
: static method, return norm of v1NormSquare(v1)
: static method, return squared norm of v1normalize()
: normalize vectornormalized()
: return a copy of the normalized vectorcopy()
: return a copy of the vector- members can be accessed with
.x
,.y
,.z
(forv3f
andv4f
),.w
(forv4f
) - 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 anglesetRotationY(angle)
: Set current matrix to be a Y axis rotation matrix of given anglesetRotationZ(angle)
: Set current matrix to be a Z axis rotation matrix of given anglepreRotateX(angle)
: Pre rotate current matrix around X axis with given anglepreRotateY(angle)
: Pre rotate current matrix around Y axis with given anglepreRotateZ(angle)
: Pre rotate current matrix around Z axis with given anglepostRotateX(angle)
: Post rotate current matrix around X axis with given anglepostRotateY(angle)
: Post rotate current matrix around Y axis with given anglepostRotateZ(angle)
: Post rotate current matrix around Z axis with given anglesetScale(sx,sy,sz)
: Set current matrix to be a scale matrix with given scale on each axispreScale(sx,sy,sz)
: Pre scale current matrix with given scale on each axispostScale(sx,sy,sz)
: Post scale current matrix with given scale on each axissetTranslation(v)
: Set current matrix to be a translation matrix of givenv3f
vectorpreTranslate(v)
: Pre translate current matrix with givenv3f
vectorpostTranslate(v)
: Post translate current matrix with givenv3f
vectorsetRotationXYZ(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 ZsetRotationZYX(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 XpreRotateXYZ(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 identitysetNull()
: Set each matrix member to 0isIdentity()
: Returntrue
if the matrix is identitytransformPoint(v)
: Transform givenv3f
vector as a point with the current matrix (apply translation)transformPoints(list_of_v)
: Transform eachv3f
vector in the given list as a point with current matrix (apply translation)transformVector(v)
: Transform givenv3f
vector with current matrix (translation is not applied)transformVectors(list_of_v)
: Transform eachv3f
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 ofCoreModifiable
with the given nameByType(type)
: Returns the list ofCoreModifiable
with the given typeGetFirstInstanceByName(name)
: Returns the firstCoreModifiable
found with the given nameGetModule(name)
: Returns the module (CoreModifiable
) with the given namePostNotification(name,sender,data)
: Post notification with the given name. sender and data are optionalCoreModifiable
parametersAddAutoUpdate(instance)
: Add givenCoreModifiable
instance to auto-update mechanismRemoveAutoUpdate(instance)
: Remove givenCoreModifiable
instance from auto-update mechanismSID(string)
: ReturnKigsID
(unsigned int) for the given stringConnect(sender,signal,receiver,slot)
: ConnectCoreModifiable
sender's signal toCoreModifiable
receiver's slotDisconnect(sender,signal,receiver,slot)
: DisconnectCoreModifiable
sender's signal toCoreModifiable
receiver's slotImport(filename)
: Import filename asCoreModifiable
tree and returnsCMSP
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
Bound 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 functionalities 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 in 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" file 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 creates a CoreModifiable
instance. The first two parameters are instance name and instance type, then the list of attributes to initialize with given values.
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 auto-update mechanism:
item("itemName1", "itemType1", {attributeName1=0,... }).items(core.AddAutoUpdate)
Find all the sample code from this wiki section in Sample7 project (browse the code).
Already Published in this Series
- Kigs Framework Introduction (1/8) - Overview
- Kigs Framework Introduction (2/8) - CoreModifiable
- Kigs Framework Introduction (3/8) - Attributes
- Kigs Framework Introduction (4/8) - Methods
- Kigs Framework Introduction (5/8) - CoreItem
- Kigs Framework Introduction (6/8) - Signal, Slot, Notification
- Kigs Framework Introduction (7/8) - Lua Binding
- Kigs Framework Introduction (8/8) - Data Driven Application
History
- 5th March, 2020: Initial version
- 17th June, 2020 : Added final article of the series
- 1st March, 2023 : Article updated after framework refactory