Kigs框架介绍 (5/8) - CoreItem






2.09/5 (3投票s)
一个多功能、跨平台、免费且开源的 C++ 框架。本文将重点介绍 CoreItem。
目录
引言
CoreItem
是一个具有多种不同用法的类族。
JSON
类型对象的操纵- 表达式求值 / 基本脚本语言
CoreModifiable
值动画
让我们来看看 Kigs 框架的这些特性。
CoreItem 基本用法
CoreItem
是用于管理 JSON
类型对象层次结构的类。
主要的 CoreItem
类型是 CoreValue
、CoreMap
和 CoreVector
。
操纵 CoreItem
的最简单方法是使用 CoreItemSP
,它是 CoreItem
的智能指针。
// Create a CoreValue<int> with value 52
CoreItemSP item = CoreItemSP(52);
以下是 CoreValue
的构造函数列表:
CoreItemSP(const bool& value)
:创建一个CoreValue<bool>
。CoreItemSP(const float& value)
:创建一个CoreValue<float>
。CoreItemSP(const int& value)
:创建一个CoreValue<int>
。CoreItemSP(const unsigned int& value)
:创建一个CoreValue<unsigned int>
。CoreItemSP(const std::string& value)
或CoreItemSP(const char* value)
:创建一个CoreValue<std::string>
。CoreItemSP(const usString& other)
:创建一个CoreValue<usString>
。
以下是 CoreVector
的构造函数列表:
CoreItemSP(const v2f& value)
:创建一个包含两个CoreValue<float>
值的CoreVector
。CoreItemSP(const v3f& value)
:创建一个包含三个CoreValue<float>
值的CoreVector
。CoreItemSP(const v4f& value)
:创建一个包含四个CoreValue<float>
值的CoreVector
。
其他静态辅助函数有:
getCoreMap()
:返回一个空的CoreMap
。getCoreVector()
:返回一个空的CoreVector
。template<typename smartPointOn, typename ... Args> static CoreItemSP getCoreItemOfType(Args&& ... args)
:返回请求的CoreItem
类型。
CoreItem
层次结构也可以从 JSON
文件或字符串创建。
// A CoreItem hierarchy can be created from json file (or json string)
JSonFileParser L_JsonParser;
CoreItemSP item = L_JsonParser.Get_JsonDictionaryFromString(R"====(
{
"obj1" : { "obj3": [0.4, 0.9, 0.0, "str"] },
"val1" : 15
}
)====");
然后可以使用类似数组的访问方式读取 Item。
// check if val2 exist
if (item["val2"].isNil())
{
std::cout << "val 2 not found " << std::endl;
}
else
{
std::cout << "val 2 : " << (int)item["val2"] << std::endl;
}
std::cout << "val 1 : " << (int)item["val1"] << std::endl;
std::cout << " first obj3 array val : " << (float)item["obj1"]["obj3"][0] << std::endl;
可以使用 set
方法将 CoreItem
插入 CoreMap
或 CoreVector
。
// create a CoreValue<float>
CoreItemSP toInsert(61.5f);
// add it to CoreMap item with key "val2"
item->set("val2", toInsert);
// set with "" do a push_back on CoreVector
item["obj1"]["obj3"]->set("",CoreItemSP("stringValue"));
maCoreItem
是 CoreModifiable
属性,可以添加到 CoreModifiable
中,然后导出或导入。
CMSP donothing = KigsCore::GetInstanceOf("useless", "DoNothing");
donothing->AddDynamicAttribute(COREITEM, "item");
donothing->setValue("item", item.get());
Export("testCoreItemExport.xml", donothing.get());
生成的 XML
文件包含一个 DATA
部分,其中包含导出的 JSON
。
<?xml version="1.0" encoding="utf-8"?>
<Inst N="useless" T="DoNothingObject">
<Attr T="coreitem" N="item" Dyn="yes">
<![CDATA[{"obj1":{"obj3":[0.400000,0.900000,0.000000,
"str","lastElem",[5.000000,4.000000,3.000000]]},
"val1":15,
"val2":52}]]>
</Attr>
</Inst>
表达式求值
另一种 CoreItem
是 CoreItemOperator
。
它们可用于使用 CoreModifiable
属性或方法来计算数学表达式。
在 C++ 代码中使用 CoreItem
表达式是作为一个字符串给出的,以 "eval
" 关键字开头,后面是表达式的维度:“1D
” 或空(表示浮点数),“2D
” 表示二维向量,“3D
” 表示三维向量,“4D
” 表示四维向量,然后是括号中的表达式。
CoreItemSP tsteval("eval(12.0*sin(4.0))");
// evaluate the expression and print it
std::cout << "Expression : 12.0*sin(4.0) = " << (float)tsteval << std::endl;
当然,也可能存在更复杂的表达式。
tsteval = std::string("eval(if(({/Sample5->randomNumber(0.0,2.0)}>1.0),
#/Sample5->EvalResult.x#=(#/Sample5->EvalResult.x#+1);1,
#/Sample5->EvalResult.y#=(#/Sample5->EvalResult.y#+1);2))");
每次我们将 CoreItem
转换为 float
、Point2D (或 v2f)
、Point3D (或 v3f)
或 Vector4D (或 v4f)
时,都会重新计算表达式。
数学运算符
- '
*
' = 乘法 - '
+
' = 加法 - '
-
' = 减法或否定 - '
/
' = 除法 - '
(
' 和 ')
' = 括号也可用于分组数学运算。
逻辑运算符
- '
==
' = 相等测试 - '
!=
' = 不等测试 - '
>
' = 大于测试 - '
<
' = 小于测试 - '
>=
' = 大于或等于测试 - '
<=
' = 小于或等于测试 - '
&&
' = 逻辑与 - '
||
' = 逻辑或
数学函数
处理浮点数值。
- '
sin
' = 计算给定参数的正弦值。 - '
cos
' = 计算给定参数的余弦值。 - '
tan
' = 计算给定参数的正切值。 - '
abs
' = 计算给定参数的绝对值。 - '
min
' = 计算给定参数的最小值。 - '
max
' = 计算给定参数的最大值。
测试和赋值
- '
if
' =if
函数接受 3 个参数,第一个是测试条件,第二个是在条件为真时返回的结果(then),第三个是在条件为假时返回的结果(else)。 - '
=
' 将右侧的值赋给左侧的属性。
属性
- '
#path_to_owner->attribute_name#
' =CoreModifiable
属性通过其路径指定。
在使用 maCoreItem
时,路径可以相对于所有者 CoreModifiable
。要仅获取二维、三维或四维向量的某个值,可以在属性名称后添加 '.x'、'.y'、'.z' 或 '.w'。
方法
- '
{path_to_owner->method_name(arg1,arg2...)}
' =CoreModifiable
方法通过其路径指定。与属性一样,在使用maCoreItem
时,路径可以相对于所有者CoreModifiable
。
向量
- '
[
' 和 ']
' = 是向量成员的分隔符。然后每个成员与下一个成员用 ',
' 分隔。
指令分隔符
- '
;
' = 可以计算多个表达式,用 ';
' 分隔。最后一个表达式是返回值。
用于 CoreModifiable 属性初始化 (XML)
可以使用相同的机制在 XML
文件中初始化属性值。
无需指定 "1D
"、"2D
"、"3D
" 或 "4D
",因为维度直接由属性类型给出。
表达式仅在初始化属性时计算一次。
<Inst N="simpleclass" T="SimpleClass">
<Attr N="IntValue" V="eval(32*4)"/>
</Inst>
动画
使用 CoreItem
的第三种方法是创建 CoreAction
动画。动画可以通过 CoreAnimation
模块实现。
这是 Sample5
的 "Screen_Main.xml" 文件中的动画示例:
<Inst Name="animateLogo" Type="CoreSequenceLauncher">
<Attr Type="coreitem" Name="Sequence"><![CDATA[
{"animateLogo":[
{"Linear2D":[4,[0.5,0.5],[1.0,0.5],"Dock"]},
{"Linear2D":[4,[1.0,0.5],[0.5,0.0],"Dock"]},
{"Combo": [
{"Hermite2D":[4,[0.5,0.0],[0.5,1.0],[-1.0,0.0],[1.0,0.0],"Dock"]},
{"Linear1D":[4,0.0,3.14,"RotationAngle"]}]},
{"SetValue1D":[1,1,"/Sample5->NeedExit"]}
]}
]]>
</Attr>
<Attr Type="bool" Name="StartOnFirstUpdate" Value="true" />
</Inst>
在前面的 XML
提取中,CoreSequenceLauncher
实例被创建为 Kigs 框架 Logo 的 UIImage
的子项。所有数值、二维、三维或四维向量 CoreModifiable
属性都可以使用 CoreAction
进行动画。CoreSequence
的创建方式如下:
{"Sequence Name":[
CoreAction1,
CoreAction2,
...
]}
每个 action 都被描述为一个 JSON
对象。
{"ActionType":[ActionParam1 , ActionParam2, ...]}
在 CoreSequence
中,每个 action 在下一个 action 之前执行。
插值 CoreAction
线性插值
可以使用 Linear1D
、Linear2D
、Linear3D
、Linear4D
。
二维、三维或四维值用 '[
' 和 ']
' 包围,并用 ',
' 分隔。
以下是 Linear2D
插值的示例:
{"Linear2D":[duration,[start_value.x,start_value.y],[end_value.x,end_value.y],
"attribute_path->attribute_name",isRelative]}
duration 是以秒为单位的浮点数,然后是起始值和结束值,然后是要进行动画的 CoreModifiable
属性,以及可选的相对属性,具有以下可能值:
- 0 => 绝对起始值和结束值。
- 1 => 起始值和结束值相对(给定的平均值将添加到当前值)。
- 2 => 起始值相对,结束值绝对。
- 3 => 起始值绝对,结束值相对。
Hermite 插值
Hermite 插值是一种具有给定起始和结束切线的插值。
以下是 Hermite1D
插值的示例(也提供 2D、3D 和 4D 版本):
{ "Hermite1D": [duration,start_value, end_value,start_tangent,
end_tangent,"attribute_path->attribute_name",isRelative] }
设置值
SetValue
action 等待 "duration" 秒,然后将给定的值设置到属性。
可以使用 SetValue1D
、SetValue2D
、SetValue3D
、SetValue4D
。
以下是 SetValue3D
的示例:
{ "SetValue3D" : [duration, [value.x,value.y,value.z] , "attribute_path->attribute_name"] }
关键帧 Action
目前,没有进行插值,KeyFrame
actions 与一系列 SetValue
actions 相同。
可以使用 KeyFrame1D
、KeyFrame2D
、KeyFrame3D
、KeyFrame4D
。
以下是 KeyFrame2D
的示例:
{"KeyFrame2D" : ["attribute_path->attribute_name", key1_time , [key1_value.x,key1_value.y]
, key2_time , [key2_value.x,key2_value.y]
, ...
, keyN_time, [keyN_value.x,keyN_value.y] ] }
循环 Action
For 循环
将同一个 action 执行 N 次。如果 N 为 -1
,则执行无限循环。
{ "ForLoop" : [N ,{ CoreAction } ] }
DoWhile 循环
当给定属性为 true(非 0)时,执行同一个 action。
{ "DoWhile" : ["attribute_path->attribute_name", { CoreAction } ] }
组合 Action
Combo
Combo
action 同时执行其所有子 action。
{ "Combo" : [{action1},
,{action2},
, ...
,{actionN} ] }
系列文章
Serie
action 按顺序播放子 action:一个接一个。
{ "Serie" :[ {action1},
,{action2},
, ...
,{actionN} ] }
函数
使用 CoreItem
表达式求值来为 CoreModifiable
属性设置动画。
可以使用 Function1D
、Function2D
、Function3D
、Function4D
。
传递表达式给 Function action 有两种可能的方式:
- 对于所需的每个维度,都会提供一个
float
(1D) 表达式。 - 提供一个与定义 action 维度相同的唯一表达式。
在表达式中可以使用 actionTime()
方法来获取当前 action 的时间。如果其中一个表达式的值为 "null
",则该参数保持不变。
Function2D
的示例。
{ "Function2D": [duration,["expression1","expression2"],"attribute_path->attribute_name"] }
或
{ "Function2D": [duration,"expression2D","attribute_path->attribute_name"] }
actionTime
用法的示例。
{ "Function2D": [2.0,["0.5+0.5*sin(actionTime())","null"],"AnchorPoint"] }
其他 Action
Wait
在给定的秒数内什么都不做。
{ "Wait" : [ duration ] }
通知
等待 duration 后发送一条消息。
可以提供一个可选字符串作为通知参数(usString
* 作为 private param
传递)。
{ "Notification" : [ duration , "notification_name", "optional_param" ] }
有关详细信息,请参阅未来的“Signal / Slot / Notification”文章。
信号
等待 duration 后,使所有者 CoreModifiable
实例发送信号。
可以提供一个可选字符串作为 usString
信号参数。
{ "Signal" : [ duration , "signal", "optional_param" ] }
有关详细信息,请参阅未来的“Signal / Slot / Notification”文章。
RemoveFromParent
等待 duration 后,从给定类型的父级中删除拥有此序列的对象。
{ "RemoveFromParent" : [ duration , "parent_type" ] }
从 Sample5 项目中查找本 Wiki 部分的所有示例代码(浏览代码)。
本系列已发布内容:
- Kigs框架介绍 (1/8) - 概述
- Kigs框架介绍 (2/8) - CoreModifiable
- Kigs框架介绍 (3/8) - 属性
- Kigs框架介绍 (4/8) - 方法
- Kigs框架介绍 (5/8) - CoreItem
- Kigs框架介绍 (6/8) - 信号,槽,通知
- Kigs框架介绍 (7/8) - Lua绑定
- Kigs框架介绍 (8/8) - 数据驱动应用程序
历史
- 2020 年 2 月 20 日:初始版本。
- 2020 年 3 月 3 日:系列中添加了文章 (6/8)。
- 2020 年 3 月 19 日:系列中添加了文章 (7/8)。
- 2020 年 6 月 17 日:添加了本系列的最后一篇文章。
- 2023年3月1日:框架重构后文章更新