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

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

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.09/5 (3投票s)

2020 年 2 月 21 日

MIT

7分钟阅读

viewsIcon

9951

一个多功能、跨平台、免费且开源的 C++ 框架。本文将重点介绍 CoreItem。

Kigs Logo

目录

引言

CoreItem 是一个具有多种不同用法的类族。

  • JSON 类型对象的操纵
  • 表达式求值 / 基本脚本语言
  • CoreModifiable 值动画

让我们来看看 Kigs 框架的这些特性。

CoreItem 基本用法

CoreItem 是用于管理 JSON 类型对象层次结构的类。

主要的 CoreItem 类型是 CoreValueCoreMapCoreVector
操纵 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 插入 CoreMapCoreVector

// 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"));

maCoreItemCoreModifiable 属性,可以添加到 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>

表达式求值

另一种 CoreItemCoreItemOperator
它们可用于使用 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 转换为 floatPoint2D (或 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",因为维度直接由属性类型给出。
表达式仅在初始化属性时计算一次。

警告:如果计算使用了其他属性(在其他实例中或不在其他实例中),则必须在当前属性之前加载并初始化它们。在给定的 XML 中,属性按照它们在 XML 中被读取的顺序进行初始化。
<Inst N="simpleclass" T="SimpleClass">
   <Attr N="IntValue" V="eval(32*4)"/>
</Inst>

动画

Sample5 animated logo snapshot

Sample5 动画 Logo 快照。

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

线性插值

可以使用 Linear1DLinear2DLinear3DLinear4D

二维、三维或四维值用 '[' 和 ']' 包围,并用 ',' 分隔。

以下是 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" 秒,然后将给定的值设置到属性。
可以使用 SetValue1DSetValue2DSetValue3DSetValue4D

以下是 SetValue3D 的示例:

{ "SetValue3D" : [duration, [value.x,value.y,value.z] , "attribute_path->attribute_name"] }

关键帧 Action

目前,没有进行插值,KeyFrame actions 与一系列 SetValue actions 相同。
可以使用 KeyFrame1DKeyFrame2DKeyFrame3DKeyFrame4D

以下是 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 属性设置动画。

可以使用 Function1DFunction2DFunction3DFunction4D

传递表达式给 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 部分的所有示例代码(浏览代码)。

本系列已发布内容:

  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 年 2 月 20 日:初始版本。
  • 2020 年 3 月 3 日:系列中添加了文章 (6/8)。
  • 2020 年 3 月 19 日:系列中添加了文章 (7/8)。
  • 2020 年 6 月 17 日:添加了本系列的最后一篇文章。
  • 2023年3月1日:框架重构后文章更新
© . All rights reserved.