cocos2dx-lua 递归开启多层子节点的透明度设置

前言

在cocos2dx-lua中如果要设置父节点和子节点的透明度,可以使用父节点的setCascadeOpacityEnabled方法开启节点透明度设置,不然无法设置节点透明度。
但是这个方法有个缺陷,当一个节点中有多层子节点时,无法开启子节点的子节点的透明度设置。网上常见的解决方案是去改引擎源码,将节点的透明度设置默认为开启。这里提供另一种解决方案。

递归开启子节点的透明度

为了能开启全部子节点的透明度设置,采用递归的方式去遍历节点的全部子节点,因为节点的层级实际上不会搞很多层(太多层想取出来进行某些操作会很麻烦),所以通常不用担心栈溢出的问题。
先贴上源码,方便介绍(已写成工具类方便调用):

local SetOpacityUtil = class("SetOpacityUtil")

function SetOpacityUtil:ctor(node)
    self.children = {};
    self.node = node;
end

--
-- @description: 先递归遍历子节点,将子节点插入table中,
-- 如果在遍历的过程中遇到没有子节点的节点或者已经遍历过的节点,就开启
-- 透明度设置,已开启设置的节点从table中移除,当table为空时结束递归。
--
function SetOpacityUtil:_setCascadeOpacity()
    if #self.children == 0 then
        return nil
    end
    -- 为子节点开启透明度设置
    if not self.children[#self.children].node:getChildren() or
        self.children[#self.children].isForEach then
        self.children[#self.children].node:setCascadeOpacityEnabled(true)
        table.remove(self.children, #self.children)
    end
    if #self.children == 0 then
        return nil
    end
    -- 如果有子节点,且该节点未遍历,就遍历它,并将该节点的子节点加到table中
    if self.children[#self.children].node:getChildren() and
        not self.children[#self.children].isForEach then
        self.children[#self.children].isForEach = true
        for _, child in ipairs(self.children[#self.children].node:getChildren()) do
            table.insert(self.children, {node = child, isForEach = false})
        end
    end
    return self:_setCascadeOpacity()
end

--
-- @Author: Y.M.Y
-- @description: 递归开启UI节点的子节点的设置透明度选项
--
function SetOpacityUtil:setCascadeOpacity()
    for _, v in pairs(self.node:getChildren()) do
        table.insert(self.children, {node = v, isForEach = false})
        self._setCascadeOpacity()
    end
    self.node:setCascadeOpacityEnabled(true)
end

return SetOpacityUtil

代码的实现思路是:

  • 先将根节点的一个子节点压入栈中;
  • 遇到没有子节点的节点或已经遍历过的节点就直接开启节点的透明度设置,并出栈;
  • 有子节点且没被标记为已遍历过的节点,就遍历该节点的全部子节点并逐一入栈。
  • 重复二、三步,直至栈为空。
  • 将下一个子节点入栈,重复上述操作,直至遍历完根节点的全部子节点。

你可能感兴趣的:(cocos2d-x,lua)