65.9K
CodeProject 正在变化。 阅读更多。
Home

Kigs框架介绍 (7/8) - Lua绑定

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.09/5 (3投票s)

2020年3月5日

MIT

8分钟阅读

viewsIcon

13758

一个多用途、跨平台的免费开源 C++ 框架。Lua 绑定功能

目录

引言

在本文中,我们将了解如何增强 Kigs 框架,特别是使用 Lua 增强 CoreModifiable 类。

Lua (5.3.5) 编程语言已嵌入到此框架中

为通用 Windows 平台构建进行了少量修改。

同一目录还包含 LuaIntf:C++11 和 Lua 语言之间的绑定

要了解更多关于 Lua 的信息,请访问:https://lua.ac.cn

绑定的框架类和方法 

以下是与 Lua 绑定的类及其可访问方法的列表

  • CoreModifiable:

    • name(): 返回实例名称
    • addItem(CMSP item): 向另一个 CoreModifiable 实例智能指针 (CMSP) 添加一个 (参见 CoreModifiable 文章)
    • removeItem(CMSP item): 从另一个 CoreModifiable 实例智能指针 (CMSP) 中移除一个 (参见 CoreModifiable 文章)
    • aggregateWith(CMSP item): 将一个 CoreModifiable 实例智能指针 (CMSP) 聚合到另一个 (参见 CoreModifiable 文章)
    • removeAggregateWith(CMSP item): 移除聚合 (参见 CoreModifiable 文章)
    • parents(): 获取父项列表
    • childs()items(): 获取子项列表
    • getSonsByType(type): 获取给定类型的子项列表
    • getSonsByName(name): 获取给定名称的子项列表
    • init(): 调用 CoreModifiable 的 Init
    • uid(): 获取实例的唯一 ID
    • type(): 获取实例的确切类型
    • isSubType(type): 检查实例是否为给定类型
    • addAttribute(val): 添加一个动态属性,类型由给定的 val (bool, float, stringvector) 决定
    • onEvent(method_name or Lua function,notification_name): 在 notification_name 上添加一个观察者,以调用 method_name 或直接的 Lua 函数。
    • getByPath(path): 通过路径搜索实例
    • importAsSon(filename): 导入给定文件,并将 CoreModifiable 树添加到调用 CoreModifiable 实例中
    • emit(signal_name): 发出具有给定名称的信号
  • CMSP :

    • get() : 获取智能指针指向的 CoreModifiable 实例
  • v2f, v3f 和 v4f : 2D、3D 或 4D 向量

    • Dot(v1,v2): 静态方法,返回 v1 和 v2 的点积
    • Cross(v1,v2): 静态方法,返回 v1 和 v2 的叉积 (v4f 不可用)
    • Norm(v1): 静态方法,返回 v1 的范数
    • NormSquare(v1): 静态方法,返回 v1 的范数的平方
    • normalize(): 归一化向量
    • normalized(): 返回归一化向量的副本
    • copy(): 返回向量的副本
    • 成员可以通过 .x, .y, .z (用于 v3fv4f), .w (用于 v4f) 访问
    • 向量的标准运算:* + - / 也可用
  • mat3x4: 3 x 4 矩阵 (3D 变换矩阵)

    • setRotationX(angle): 将当前矩阵设置为给定角度的 X 轴旋转矩阵
    • setRotationY(angle): 将当前矩阵设置为给定角度的 Y 轴旋转矩阵
    • setRotationZ(angle): 将当前矩阵设置为给定角度的 Z 轴旋转矩阵
    • preRotateX(angle): 在当前矩阵的 X 轴上以给定角度预先旋转
    • preRotateY(angle): 在当前矩阵的 Y 轴上以给定角度预先旋转
    • preRotateZ(angle): 在当前矩阵的 Z 轴上以给定角度预先旋转
    • postRotateX(angle): 在当前矩阵的 X 轴上以给定角度后置旋转
    • postRotateY(angle): 在当前矩阵的 Y 轴上以给定角度后置旋转
    • postRotateZ(angle): 在当前矩阵的 Z 轴上以给定角度后置旋转
    • setScale(sx,sy,sz): 将当前矩阵设置为在每个轴上具有给定比例的缩放矩阵
    • preScale(sx,sy,sz): 在每个轴上以给定比例预先缩放当前矩阵
    • postScale(sx,sy,sz): 在每个轴上以给定比例后置缩放当前矩阵
    • setTranslation(v): 将当前矩阵设置为给定 v3f 向量的平移矩阵
    • preTranslate(v): 用给定的 v3f 向量预先平移当前矩阵
    • postTranslate(v): 用给定的 v3f 向量后置平移当前矩阵
    • setRotationXYZ(aX,aY,aZ): 将当前矩阵设置为具有角度 aX, aY, aZ 的旋转矩阵。旋转按 X、然后 Y、然后 Z 的顺序应用
    • setRotationZYX(aX,aY,aZ): 将当前矩阵设置为具有角度 aX, aY, aZ 的旋转矩阵。旋转按 Z、然后 Y、然后 X 的顺序应用
    • preRotateXYZ(aX,aY,aZ): 预先旋转当前矩阵 (旋转按 X、然后 Y、然后 Z 的顺序应用)
    • preRotateZYX(aX,aY,aZ): 预先旋转当前矩阵 (旋转按 Z、然后 Y、然后 X 的顺序应用)
    • postRotateXYZ(aX,aY,aZ): 后置旋转当前矩阵 (旋转按 X、然后 Y、然后 Z 的顺序应用)
    • postRotateZYX(aX,aY,aZ): 后置旋转当前矩阵 (旋转按 Z、然后 Y、然后 X 的顺序应用)
    • setIdentity(): 将矩阵设置为单位矩阵
    • setNull(): 将矩阵的每个成员设置为 0
    • isIdentity(): 如果矩阵是单位矩阵,则返回 true
    • transformPoint(v): 使用当前矩阵转换给定的 v3f 向量作为一个点 (应用平移)
    • transformPoints(list_of_v): 使用当前矩阵转换给定列表中的每个 v3f 向量作为一个点 (应用平移)
    • transformVector(v): 使用当前矩阵转换给定的 v3f 向量 (不应用平移)
    • transformVectors(list_of_v): 使用当前矩阵转换给定列表中的每个 v3f 向量 (不应用平移)
    • copy(): 返回当前矩阵的副本
  • 核心:

    • ByName(name): 返回具有给定名称的 CoreModifiable 列表
    • ByType(type): 返回具有给定类型的 CoreModifiable 列表
    • GetFirstInstanceByName(name): 返回找到的第一个具有给定名称的 CoreModifiable 实例
    • GetModule(name): 返回具有给定名称的模块 (CoreModifiable)
    • PostNotification(name,sender,data): 发布具有给定名称的通知。sender 和 data 是可选的 CoreModifiable 参数
    • AddAutoUpdate(instance): 将给定的 CoreModifiable 实例添加到自动更新机制
    • RemoveAutoUpdate(instance): 从自动更新机制中移除给定的 CoreModifiable 实例
    • SID(string): 返回给定字符串的 KigsID (无符号整数)
    • Connect(sender,signal,receiver,slot): 将 CoreModifiable 发送方的信号连接到 CoreModifiable 接收方的槽
    • Disconnect(sender,signal,receiver,slot): 断开 CoreModifiable 发送方的信号与 CoreModifiable 接收方的槽的连接
    • Import(filename): 导入文件名为 CoreModifiable 树,并返回 CMSP

从 Lua 访问 Kigs 框架

在 Lua 端,框架的通用功能是可用的

-- 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 属性可以直接通过其名称后跟点 '.' 来访问。

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

绑定的方法或 CoreModifiable 方法通过经典的 Lua 方式使用 ':' (静态方法除外,静态方法应使用 '.')

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

从 Kigs 框架访问 Lua

执行 Lua 代码

可以直接从 C++ 中的文件执行一些 Lua 代码

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

或者在导入 XML 文件时通过向实例添加 "Lua" 项来执行一些代码

<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>

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

向实例添加 Lua 方法

在 XML 中,也可以将 Lua 函数 (作为 CoreModifiable 方法) 添加到 CoreModifiable 实例

<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 类

LuaBehaviour 类用于使用 Lua 语言向实例添加功能。

序列化

最简单的方法是直接在 XML 中将此类项添加到目标实例

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

LuaBehaviour 必须作为聚合项添加到其父实例。

在此,"Script" 属性的值为 "#test.lua"。开头的 '#' 表示要加载的文件名。因此,此处会加载 (如果找到) "test.lua" 文件,并将其内容解释为 Lua。

代码也可以作为 CDATA 嵌入到 XML 文件中

<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>

在 C++ 代码中

当然,可以使用框架代码以 "经典" 方式创建 LuaBehaviour 实例

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

Lua 端语法

行为代码

Lua 代码必须是以下形式

-- 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 

当聚合项初始化、更新等时,"init()", "update(current_time)", "destroy()", "addItem(other)", "removeItem(other)" 这些方法会被自动调用

在 Lua 中直接添加 CoreModifiable Lua 方法,可以使用对象声明中的 WRAP_METHODS 表。

-- 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

或者直接在 `init` 函数中向目标对象添加 Lua 函数

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

因此,在 C++ 端,可以像调用其他 CoreModifiable 方法一样调用 Lua 的 reset 方法

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

从 LuaBehaviour 访问 CoreModifiable 实例

LuaBehaviour 函数可以使用 self.target 来访问聚合到 LuaBehaviourCoreModifiable 实例

-- 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 类

也可以使用 LuaImporter 类导入用 Lua 创建的 CoreModifiable 树。

在 XML 中,添加以下项以导入 "scene.lua" 文件并将其添加到当前 XML 层级结构中

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

用于导入的 Lua 文件的语法如下

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

"item" 关键字创建 CoreModifiable 实例。前两个参数是实例名称和实例类型,然后是要用给定值初始化的属性列表。

要向项添加子项,请使用 ".items" 关键字。

在上面的示例中,itemName2itemName3itemName1 的子项。

由于是 Lua 代码,可以定义函数并调用它们作为辅助函数,以创建相同类型的对象或初始化属性

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

也可以从另一个 XML 或 Lua 文件导入项

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

或者使用 "ref" 关键字引用已加载的项: 

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

最后,还可以连接信号和槽

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

并将实例添加到自动更新机制

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

在此 Wiki 部分找到所有示例代码,位于 Sample7 项目中 (浏览代码)。

已在此系列中发布

  1. Kigs框架介绍 (1/8) - 概述
  2. Kigs框架介绍 (2/8) - CoreModifiable
  3. Kigs框架介绍 (3/8) - 属性
  4. Kigs框架介绍 (4/8) - 方法
  5. Kigs框架介绍 (5/8) - CoreItem
  6. Kigs框架介绍 (6/8) - 信号,槽,通知
  7. Kigs框架介绍 (7/8) - Lua绑定
  8. Kigs框架介绍 (8/8) - 数据驱动应用程序

历史

  • 2020 年 3 月 5 日:初始版本
  • 2020 年 6 月 17 日:添加了该系列的最后一篇文章
  • 2023 年 3 月 1 日:框架重构后更新了文章
© . All rights reserved.