11.【cocos2d-x 源码分析】:UI系统的详细分析(中)

本文深入剖析了cocos2d-x 3.3版本UI系统的核心原理,重点关注了UI组件的实现细节,为读者揭示了UI系统的工作机制。文章详述了部分关键源码,为后续分析具体UI控件的实现奠定了基础。
摘要由CSDN通过智能技术生成
对应源码位置:cocos2d-x-3.3\cocos\ui\UI*
Layout的原理

这里选取少量的重点部分。

//找当前节点的下一个可以聚焦的节点
//主要看思想  已经删了很多了
Widget* Layout::getNextFocusedWidget(FocusDirection direction, Widget *current)
{
   
    Widget *nextWidget = nullptr;
    ssize_t previousWidgetPos = _children.getIndex(current);
    //选取下一个 孩子节点
    previousWidgetPos = previousWidgetPos + 1;  
    if (previousWidgetPos < _children.size())
    {
   
    	//找下一个Widget
        nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
        //handle widget
        if (nextWidget)
        {
   
        	//可以聚焦再看
            if (nextWidget->isFocusEnabled())
            {
   
                //如果是个 Layout 就在里面找 直到找到一个控件
                Layout* layout = dynamic_cast<Layout*>(nextWidget);
                if (layout)
                {
   
                    layout->_isFocusPassing = true;
                    return layout->findNextFocusedWidget(direction, layout);
                }
                else
                {
   
                	//否则 就是你了 回调一下
                    this->dispatchFocusEvent(current, nextWidget);
                    return nextWidget;
                }
            }
            else
            {
   
                return this->getNextFocusedWidget(direction, nextWidget);
            }
        }
        else
        {
   
            return current;
        }
    }
}
//看看 Layout具体怎么绘制
//这就是Node 节点都有的 visit
void Layout::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
   
    if (!_visible)
    {
   
        return;
    }
    //空函数
    adaptRenderers();
    //核心部分  处理布局 后面详细
    doLayout();
    //先假装  不满足 直走else
    if (_clippingEnabled)
    {
   
        switch (_clippingType)
        {
   
            case ClippingType::STENCIL:
                stencilClippingVisit(renderer, parentTransform, parentFlags);
                break;
            case ClippingType::SCISSOR:
                scissorClippingVisit(renderer, parentTransform, parentFlags);
                break;
            default:
                break;
        }
    }
    //就是以前普通的visit
    else
    {
   
        Widget::visit(renderer, parentTransform, parentFlags);
    }
}
//处理布局的核心
void Layout::doLayout()
{
   
    //如果布局没有变化
    if (!_doLayoutDirty)
    {
   
        return;
    }
    //排序
    sortAllChildren();
	//创建 Layoutmanager
    LayoutManager* executant = this->createLayoutManager();
    
    if (executant)
    {
   
    	//核心部分
        executant->doLayout(this);
    }
    
    _doLayoutDirty = false;
}
//就是根据布局的类型生成对应的manager
LayoutManager* Layout::createLayoutManager()
{
   
    LayoutManager* exe = nullptr;
    switch (_layoutType)
    {
   
        case Type::VERTICAL:
            exe = LinearVerticalLayoutManager::create();
            break;
        case Type::HORIZONTAL:
            exe = LinearHorizontalLayoutManager::create();
            break;
        case Type::RELATIVE:
            exe = RelativeLayoutManager::create();
            break;
        default:
            break;
    }
    return exe;

}

LayoutManager 的分析


class CC_GUI_DLL LayoutManager : public Ref
{
   
public:
    virtual ~LayoutManager(){
   };
    LayoutManager(){
   };
    //虚函数
    virtual void doLayout(LayoutProtocol *layout) = 0;
    
    friend class Layout;
};
//垂直的线性布局
class CC_GUI_DLL LinearVerticalLayoutManager : public LayoutManager
{
   
private:
    LinearVerticalLayoutManager(){
   };
    virtual ~LinearVerticalLayoutManager(){
   };
    static LinearVerticalLayoutManager* create();
    virtual void doLayout(LayoutProtocol *layout) override;
    
    friend class Layout;
};
//水平的线性布局
class CC_GUI_DLL LinearHorizontalLayoutManager : public LayoutManager
{
   
private:
    LinearHorizontalLayoutManager(){
   };
    virtual ~LinearHorizontalLayoutManager(){
   };
    static LinearHorizontalLayoutManager* create();
    virtual void doLayout(LayoutProtocol *layout) override;
    
    friend class Layout;
};
//具体实现 选一个  其思想就是 计算出最终的位置  相对布局更加复杂
void LinearHorizontalLayoutManager::doLayout(LayoutProtocol* layout)
{
   
	//获取布局本身的大小
    Size layoutSize = layout->getLayoutContentSize();
    //获取布局的孩子节点
    Vector<Node*> container = layout->getLayoutElements();
    float leftBoundary = 0.0f;
    for (auto& subWidget : container)
    {
   
    	//获取这个控件
        Widget* child = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值