【Cocos2dx】【二】fairyGUI lua 接入

【Cocos2dx】【二】fairyGUI lua 接入

官方文档

或者看这篇官方推荐的博客:

FairyGUI在Cocos2d-x下的多平台接入和lua绑定

其中有两个步骤暂时不理解。

一.conversions.yaml

definitions:
  # the names of the functions - we use this to generate the code and to register the functions in
  # the javascript class
  ifunction: "lua_${generator.prefix}_${class_name}_${func_name}"
  sfunction: "lua_${generator.prefix}_${class_name}_${func_name}"
  constructor: "lua_${generator.prefix}_${class_name}_constructor"
conversions:
  # some times you want to use a special native type when converting from spidermonkey to native
  # the most common case would be from JS-boolean to bool. Using "bool" will fail here since we
  # pass the address to the conversion method, and a JSBool is defined as an integer in spidermonkey
  native_types:
    float: "double"
    short: "int32_t"
    "unsigned char": "uint16_t"
    "char": "int32_t"
  ns_map:
  	......
  	......
    "fairy::": "fgui."

  to_native:
    # lua to native
    int: "ok &= luaval_to_int32(tolua_S, ${arg_idx},(int *)&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "unsigned int": "ok &= luaval_to_uint32(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "unsigned char": "ok &= luaval_to_uint16(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    short: "ok &= luaval_to_int32(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "unsigned short": "ok &= luaval_to_ushort(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    char: "ok &= luaval_to_int32(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    bool: "ok &= luaval_to_boolean(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    float: "ok &= luaval_to_number(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    double: "ok &= luaval_to_number(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    ssize_t: "ok &= luaval_to_ssize_t(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "long long": "ok &= luaval_to_long_long(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "string": "ok &= luaval_to_std_string(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "string_view": "ok &= luaval_to_std_string_view(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
    "String*": "std::string ${out_value}_tmp; ok &= luaval_to_std_string(tolua_S, ${arg_idx}, &${out_value}_tmp, \"${lua_namespaced_class_name}:${func_name}\"); ${out_value} = ax::String::create(${out_value}_tmp)"
    "char*": "std::string ${out_value}_tmp; ok &= luaval_to_std_string(tolua_S, ${arg_idx}, &${out_value}_tmp, \"${lua_namespaced_class_name}:${func_name}\"); ${out_value} = ${out_value}_tmp.c_str()"
    "Point": "ok &= luaval_to_point(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
	
	......
	......
	......

    object: "ok &= luaval_to_object<${arg.to_string($generator).replace(\"*\", \"\")}>(tolua_S, ${arg_idx}, \"${scriptname}\",&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"
  from_native:
    # native to lua
    int: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "unsigned int": "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "unsigned short": "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "unsigned char": "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    short: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    char: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "long long": "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "string": "lua_pushlstring(tolua_S,${in_value}.c_str(),${in_value}.length())"
    "string_view": "lua_pushlstring(tolua_S,${in_value}.data(),${in_value}.length())"
    "__thread_id": "std_thread_id_to_luaval(tolua_S, ${in_value})"
    "char*": "tolua_pushstring(tolua_S,(const char*)${in_value})"
    "String*": "tolua_pushstring(tolua_S, ${in_value}->getCString())"
    bool: "tolua_pushboolean(tolua_S,(bool)${in_value})"
    float: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    double: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    long: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    ssize_t: "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "unsigned long": "tolua_pushnumber(tolua_S,(lua_Number)${in_value})"
    "Point": "point_to_luaval(tolua_S, ${in_value})"
	
	......
	......
	......
	
    object: "object_to_luaval<${ntype.replace(\"*\", \"\").replace(\"const \", \"\")}>(tolua_S, \"${scriptname}\",(${ntype.replace(\"const \", \"\")})${in_value})"

1.什么是yaml?

在这里插入图片描述
在这里插入图片描述
查阅了以下,就是 xml 、json 这种东西。数据按照固定规则排布的数据文件。.yml 和 .yaml是它的文件后缀。

2.文件内容和什么是Margin?

在这里插入图片描述
没有在 conversions.yaml添加代码会报这个错误。而Margin指的是fairygui自带的Margin类。

那这行代码是啥意思呢?为什么不在 yaml 中填它的配置就会这样?先看看yaml各参数。

a.ns_map:

FairyGUIMacros.h
在这里插入图片描述

	ns_map:
	// C++ | lua
	//错误的
    "fairy::": "fgui."
	//正确的
	“fairygui::”:"fgui."

ns_map 是对应关系,左边是 fairygui C++ 里的命名空间,右边对应的是在lua中的命名空间。

  1. 左侧的是C++对应的命名空间,一定要填对,找到fairygui在C++使用的命名空间名称。填错会有这个报错。

    Exception: The namespace (fairygui::UIConfig) conversion wasn’t set in ‘ns_map’ section of the conversions.yaml

  2. 右侧的是lua里的命名空间,记得也要填对。因为这里也会在生成中,匹配替换到代码里。

很纳闷,这里的 fgui. 不会和 .ini 里重复了吗?待测试。

b.to_native:

指的是Lua这边传出的数据,对应C++要如何处理。并且在生成的时候,会进行对应的匹配替换。

  "Point": "ok &= luaval_to_point(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"

c.from_native:

反过来的,C++这边传出的类型,对应的是Lua这边的哪个类型,以及处理。并且在生成的时候,会进行对应的匹配替换。

  "Point": "point_to_luaval(tolua_S, ${in_value})"

二.manual

1.LuaBasicConversion .cpp .hpp

conversions.yaml 有关。配置文件中,在 to_nativefrom_native 中填入了 fairygui::Margin 与 lua 交互时,应该如何传递数据。

比如自定义类 Point

  "Point": "ok &= luaval_to_point(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")"

LuaBasicConversion .cpp

/**
 * Get a Vec2 object value from the given acceptable index of stack.
 * At current, the Point is typedef of Vec2.
 * @see luaval_to_vec2
 */
static inline bool luaval_to_point(lua_State* L, int lo, cc::Vec2* outValue, const char* funcName = "")
{
    return luaval_to_vec2(L, lo, outValue);
}

bool luaval_to_vec2(lua_State* L, int lo, cc::Vec2* outValue, const char* funcName)
{
    if (nullptr == L || nullptr == outValue)
        return false;

    bool ok = true;

    tolua_Error tolua_err;
    //是不是table
    if (!tolua_istable(L, lo, 0, &tolua_err))
    {
#if _COCOS_DEBUG >= 1
        luaval_to_native_err(L, "#ferror:", &tolua_err, funcName);
#endif
        ok = false;
    }

    // assertion: since we only have vec2, you should never passing rect as vec2 to native
    const auto objlen = lua_objlen(L, lo);
    assert(objlen != 4);

    if (ok)
    {
    	// x 压入栈中
        lua_pushstring(L, "x");
        // 获取 lo 深度的 table
        lua_gettable(L, lo);
        // 栈顶是否为nil
        if (lua_isnil(L, -1))
        {
            lua_pop(L, 1);
            lua_pushstring(L, "width");
            lua_gettable(L, lo);
        }
		
		// 从栈中获取x值
        outValue->x = lua_isnil(L, -1) ? 0.0f : (float)lua_tonumber(L, -1);
        //清空栈
        lua_pop(L, 1);
		
		// 重复取x的步骤来获取y
        lua_pushstring(L, "y");
        lua_gettable(L, lo);
        if (lua_isnil(L, -1))
        {
            lua_pop(L, 1);
            lua_pushstring(L, "height");
            lua_gettable(L, lo);
        }

        outValue->y = lua_isnil(L, -1) ? 0.0f : (float)lua_tonumber(L, -1);
        lua_pop(L, 1);
    }
    return ok;
}

而 LuaBasicConversion 里写的就是这些转换的逻辑代码(luaval_to_point等)。

一般int,float这种是不需要咱们写的,只需要写出来一些自己定义的,需要特殊逻辑处理的类型即可。

2.fairygui::Margin —> LuaBasicConversion

如上面的代码,就得自己写一个luaval_to_margin了。当然,可以咱们自己练练手,也可以直接拿其他人写好的。因为fairygui很多项目和demo以及cocos的社区版都实现过,咱们直接拿来对比拷贝以下就可以了。

Cocos2d-Lua-Community - Cocos2dx社区版

= = 额,社区版的竟然没写在 LuaBasicConversion 里,而是直接写在了manual里,牛的。

流程没问题,能对的上就行。

3.lua_xxx_manual.cpp .hpp

根据个人观察, lua_xxx_manual 基本都是放一些拓展和总入口用的。

拿社区般的 spine manual 来看看,总共有这些代码文件。
在这里插入图片描述lua_cocos2dx_spine_manual.cpp

注册,LuaStack调用的

// c++注册lua
int register_spine_module(lua_State* L)
{
    lua_getglobal(L, "_G");
    if (lua_istable(L,-1))//stack:...,_G,
    {
    	// auto里。
    	// 注册auto生成的
        register_all_cocos2dx_spine(L);
        // 同个文件,没贴出来。
        // 注册manual需要的
        register_spine_manual(L);
        //下面哪个  lua_spSkeletonData.cpp 里。
        // 注册它需要的
        register_spSkeletonData_manual(L);
    }
    lua_pop(L, 1);

    return 1;
}

manaul样例

static int lua_cocos2dx_spine_SkeletonAnimation_createWithData(lua_State* L)
{
    if (nullptr == L)
        return 0 ;
    
    int argc = 0;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertable(L,1,"sp.SkeletonAnimation",0,&tolua_err)) goto tolua_lerror;
#endif
    
    argc = lua_gettop(L) - 1;
    
    if (1 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!tolua_isusertype(L,2,"sp.SkeletonData",0,&tolua_err)) goto tolua_lerror;
#endif
        lua_spSkeletonData *luaSpData = static_cast<lua_spSkeletonData *>(tolua_tousertype(L,2,0));
        auto tolua_ret = LuaSkeletonAnimation::createWithData(luaSpData->data, false);
        
        int nID = (tolua_ret) ? (int)tolua_ret->_ID : -1;
        int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL;
        toluafix_pushusertype_ccobject(L, nID, pLuaID, (void*)tolua_ret,"sp.SkeletonAnimation");
        return 1;
    }
    
    luaL_error(L, "'createWithData' function of SkeletonAnimation has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'createWithData'.",&tolua_err);
#endif
    return 0;
}


-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------


static int lua_cocos2dx_spine_SkeletonAnimation_createWithJsonFile(lua_State* L)
{
    if (nullptr == L)
        return 0 ;
    
    int argc = 0;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertable(L,1,"sp.SkeletonAnimation",0,&tolua_err)) goto tolua_lerror;
#endif
    
    argc = lua_gettop(L) - 1;
    
    if (2 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!tolua_isstring(L, 2, 0, &tolua_err)  ||
            !tolua_isstring(L, 3 ,0, &tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        const char* skeletonDataFile = tolua_tostring(L, 2, "");
        const char* atlasFile = tolua_tostring(L, 3, "");;
        auto tolua_ret = LuaSkeletonAnimation::createWithJsonFile(skeletonDataFile, atlasFile);
        
        int nID = (tolua_ret) ? (int)tolua_ret->_ID : -1;
        int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL;
        toluafix_pushusertype_ccobject(L, nID, pLuaID, (void*)tolua_ret,"sp.SkeletonAnimation");
        return 1;
    } else if (3 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!tolua_isstring(L, 2, 0, &tolua_err)  ||
            !tolua_isstring(L, 3 ,0, &tolua_err)  ||
            !tolua_isnumber(L, 4 ,0, &tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        const char* skeletonDataFile = tolua_tostring(L, 2, "");
        const char* atlasFile = tolua_tostring(L, 3, "");
        LUA_NUMBER scale = tolua_tonumber(L, 4, 1);
        
        auto tolua_ret = LuaSkeletonAnimation::createWithJsonFile(skeletonDataFile, atlasFile, scale);
        
        int nID = (tolua_ret) ? (int)tolua_ret->_ID : -1;
        int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL;
        toluafix_pushusertype_ccobject(L, nID, pLuaID, (void*)tolua_ret,"sp.SkeletonAnimation");
        return 1;
    }
    
    luaL_error(L, "'createWithJsonFile' function of SkeletonAnimation has wrong number of arguments: %d, was expecting %d\n", argc, 2);
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'createWithJsonFile'.",&tolua_err);
#endif
    return 0;
}

比如这两个

  • lua_cocos2dx_spine_SkeletonAnimation_createWithData

    没太懂为啥要自己写

  • lua_cocos2dx_spine_SkeletonAnimation_createWithJsonFile

    这个就简单了,根据不同参数调用不同生成方法而已

其他的功用就请自行去看了,我也没有很深的了解了。

猜你喜欢

转载自blog.csdn.net/qq_28686039/article/details/128983439