转载

cocos2d-x的lua脚本加载CocostudioUI文件

前言

当前版本使用的是quick cocos2dx lua 3.3。UI使用cocostudio编辑器。我们在程序里面可以使用两种方式进行解析UI。开始的时候用的是quick的方法,结果遇到了坑(百分比控件布局,你们可以自己试一下什么效果)。

我在后面简单提一下,不过不是自己遇到的坑,就不知道有多坑。

一.quick使用cocostudio

1.加载

local uiNode = cc.uiloader:load("TestUI.json") self:addChild(uiNode)
cc.uiloader:load("XXXX.json") 后面的参数是你的cocostudio导出文件,注意路径问题

2.读取控件

在程序中获取控件的方法,我们可以看下 framework/cc/uiloader/uiloader.lua, (CCSUILoader.lua文件可以看下,讲具体怎么实现的)

-- @module uiloader --[[-- 初始化 cc.uiloader,并提供对外统一接口 cc.uiloader 可以将CCS导出的json文件用quick的纯lua控件构建出UI布局 ]] local UILoaderUtilitys = import(".UILoaderUtilitys") local uiloader = class("uiloader") local CCSUILoader = import(".CCSUILoader") local CCSSceneLoader = import(".CCSSceneLoader") -- start -- -------------------------------- -- 初始化 cc.uiloader,并提供对外统一接口 -- @function [parent=#uiloader] new -- end -- function uiloader:ctor() end -- start -- -------------------------------- -- 解析json文件 -- @function [parent=#uiloader] load -- @param string jsonFile 要解析的json文件 -- @param table params 解析参数 -- @return node#node  解析后的布局 -- end -- function uiloader:load(jsonFile, params)  local json  if not params or not params.bJsonStruct then   local pathInfo = io.pathinfo(jsonFile)   if ".csb" == pathInfo.extname then    return cc.CSLoader:getInstance():createNodeWithFlatBuffersFile(jsonFile)   else    json = self:loadFile_(jsonFile)   end  else   json = jsonFile  end  if not json then   print("uiloader - load file fail:" .. jsonFile)   return  end  local node  if self:isScene_(json) then   node, w, h = CCSSceneLoader:load(json, params)  else   node, w, h = CCSUILoader:load(json, params)  end  UILoaderUtilitys.clearPath()  return node, w, h end -- start -- -------------------------------- -- 按tag查找布局中的结点 -- @function [parent=#uiloader] seekNodeByTag -- @param node parent 要查找布局的结点 -- @param number tag 要查找的tag -- @return node#node  -- end -- function uiloader:seekNodeByTag(parent, tag)  if not parent then   return  end  if tag == parent:getTag() then   return parent  end  local findNode  local children = parent:getChildren()  local childCount = parent:getChildrenCount()  if childCount < 1 then   return  end  for i=1, childCount do   if "table" == type(children) then    parent = children[i]   elseif "userdata" == type(children) then    parent = children:objectAtIndex(i - 1)   end   if parent then    findNode = self:seekNodeByTag(parent, tag)    if findNode then     return findNode    end   end  end  return end -- start -- -------------------------------- -- 按name查找布局中的结点 -- @function [parent=#uiloader] seekNodeByName -- @param node parent 要查找布局的结点 -- @param string name 要查找的name -- @return node#node  -- end -- function uiloader:seekNodeByName(parent, name)  if not parent then   return  end  if name == parent.name then   return parent  end  local findNode  local children = parent:getChildren()  local childCount = parent:getChildrenCount()  if childCount < 1 then   return  end  for i=1, childCount do   if "table" == type(children) then    parent = children[i]   elseif "userdata" == type(children) then    parent = children:objectAtIndex(i - 1)   end   if parent then    if name == parent.name then     return parent    end   end  end  for i=1, childCount do   if "table" == type(children) then    parent = children[i]   elseif "userdata" == type(children) then    parent = children:objectAtIndex(i - 1)   end   if parent then    findNode = self:seekNodeByName(parent, name)    if findNode then     return findNode    end   end  end  return end -- start -- -------------------------------- -- 按name查找布局中的结点 -- 与seekNodeByName不同之处在于它是通过node的下子结点表来查询,效率更快 -- @function [parent=#uiloader] seekNodeByNameFast -- @param node parent 要查找布局的结点 -- @param string name 要查找的name -- @return node#node  -- end -- function uiloader:seekNodeByNameFast(parent, name)  if not parent then   return  end  if not parent.subChildren then   return  end  if name == parent.name then   return parent  end  local findNode = parent.subChildren[name]  if findNode then   -- find   return findNode  end  for i,v in ipairs(parent.subChildren) do   findNode = self:seekNodeByName(v, name)   if findNode then    return findNode   end  end  return end -- start -- -------------------------------- -- 根据路径来查找布局中的结点 -- @function [parent=#uiloader] seekNodeByPath -- @param node parent 要查找布局的结点 -- @param string path 要查找的path -- @return node#node  -- end -- function uiloader:seekNodeByPath(parent, path)  if not parent then   return  end  local names = string.split(path, '/')  for i,v in ipairs(names) do   parent = self:seekNodeByNameFast(parent, v)   if not parent then    return   end  end  return parent end -- start -- -------------------------------- -- 查找布局中的组件结点 -- @function [parent=#uiloader] seekComponents -- @param node parent 要查找布局的结点 -- @param string nodeName 要查找的name -- @param number componentIdx 在查找组件在它的直接父结点的位置 -- @return node#node  --[[-- 查找布局中的组件结点 ~~~ lua -- "hero" 是结点名称 -- 1 是 "hero"这个结点下的第一个组件 local hero = cc.uiloader:seekComponents(parentNode, "hero", 1) ~~~ ]] -- end -- function uiloader:seekComponents(parent, nodeName, componentIdx)  local node = self:seekNodeByName(parent, nodeName)  if not node then   return  end  node = self:seekNodeByName(node, "Component" .. componentIdx)  return node end -- private function uiloader:loadFile_(jsonFile)  local fileUtil = cc.FileUtils:getInstance()  local fullPath = fileUtil:fullPathForFilename(jsonFile)  local pathinfo  = io.pathinfo(fullPath)  UILoaderUtilitys.addSearchPathIf(pathinfo.dirname)  local jsonStr = fileUtil:getStringFromFile(fullPath)  local jsonVal = json.decode(jsonStr)  return jsonVal end function uiloader:isScene_(json)  if json.components then   return true  else   return false  end end return uiloader 

button我们肯定会和他打交道的,这里我说下。在CCSUILoader.lua中我们可以看到,这里加载的是quick自己的button控件

如果我们没有在cocostudio中设置button的选中和禁止图片,这里点击是没有任何效果的,而使用c++时,会点击方法效果,我们可以根据自己的需求做相应修改

function CCSUILoader:createButton(options)  local node = cc.ui.UIPushButton.new(self:getButtonStateImages(options),   {scale9 = options.scale9Enable,   flipX = options.flipX,   flipY = options.flipY})  if options.opacity then   node:setCascadeOpacityEnabled(true)   node:setOpacity(options.opacity)  end  if options.text then   node:setButtonLabel(    cc.ui.UILabel.new({text = options.text,     size = options.fontSize,     color = cc.c3b(options.textColorR, options.textColorG, options.textColorB)}))  end  if not options.ignoreSize then   node:setButtonSize(options.width, options.height)  end  node:align(self:getAnchorType(options.anchorPointX or 0.5, options.anchorPointY or 0.5),   options.x or 0, options.y or 0)  return node end 

下面是一个读取按钮的例子:

local button = cc.uiloader:seekNodeByPath(self.uiNode, buttonName) if button ~= nil then     button:addButtonClickedEventListener(function(...)    self:onCickSublistButton() end)

二.cocos2dx自带使用cocostudio

我觉得这个还是比较好的,因为触控一直在更新完善。而quick目前是没有在维护。

1.加载

local uiNode = ccs.GUIReader:getInstance():widgetFromJsonFile("Test.json")
uiNode:addTo(self)

可以参考GUIReader.lua 或者GUIReader.h (GUIReader.lua 是c++绑定到lua 时生成的api)

2.读取控件

这里控件的解析我们使用的是Helper ,可以参考 api Helper.lua 和具体的c++类Helper.h

-------------------------------- -- @module Helper -- @parent_module ccui -------------------------------- -- brief Get a UTF8 substring from a std::string with a given start position and length<br> -- Sample:  std::string str = "中国中国中国";  substr = getSubStringOfUTF8String(str,0,2) will = "中国"<br> -- param start The start position of the substring.<br> -- param length The length of the substring in UTF8 count<br> -- return a UTF8 substring -- @function [parent=#Helper] getSubStringOfUTF8String  -- @param self -- @param #string str -- @param #unsigned long start -- @param #unsigned long length -- @return string#string ret (return value: string) -------------------------------- --  -- @function [parent=#Helper] changeLayoutSystemActiveState  -- @param self -- @param #bool bActive -------------------------------- --  -- @function [parent=#Helper] seekActionWidgetByActionTag  -- @param self -- @param #ccui.Widget root -- @param #int tag -- @return Widget#Widget ret (return value: ccui.Widget) -------------------------------- -- Finds a widget whose name equals to param name from root widget.<br> -- param root      widget which will be seeked.<br> -- name      name value.<br> -- return finded result. -- @function [parent=#Helper] seekWidgetByName  -- @param self -- @param #ccui.Widget root -- @param #string name -- @return Widget#Widget ret (return value: ccui.Widget) -------------------------------- -- Finds a widget whose tag equals to param tag from root widget.<br> -- param root      widget which will be seeked.<br> -- tag      tag value.<br> -- return finded result. -- @function [parent=#Helper] seekWidgetByTag  -- @param self -- @param #ccui.Widget root -- @param #int tag -- @return Widget#Widget ret (return value: ccui.Widget) -------------------------------- --  -- @function [parent=#Helper] doLayout  -- @param self -- @param #cc.Node rootNode return nil 

下面是button的例子:

local button = ccui.Helper:seekWidgetByName(self.uiNode, buttonName)
function CampMainlayer:initButton()  local function touchEvent(sender,event)    if event == ccui.TouchEventType.ended then    if sender ~= nil then     local tag = sender:getTag()-1000     --TODO:操作    end    end  end  for i=1,3 do   local buttonName = "Button_"..i   local button = ccui.Helper:seekWidgetByName(self.uiNode, buttonName)   if button ~= nil then     button:addTouchEventListener(touchEvent)    button:setTag(1000+i)   end  end end 

注意 ccui.TouchEventType.ended  这是在 cocos.ui.GuiConstants中,所以我们想用这些的话,需要 require("cocos.ui.GuiConstants")。

我们在实际的项目开发中,肯定会遇到很多问题,当然,遇到问题我们可以在网上找,但是并不是所有的问题都能找到,所以,自己动手解决问题的能力很重要,

对于我们来说,去看源码,看具体的实现,就能很快找到解决问题的方式。

如果有什么问题,请加我的QQ776274781,或者群:102349463 。大家一起学习。

正文到此结束
Loading...