【Cocos2d-x】源码分析之 2d/ui/UILayout

来源:互联网 发布:全民枪战刷炎龙软件 编辑:程序博客网 时间:2024/06/05 01:10
#ifndef __LAYOUT_H__#define __LAYOUT_H__#include "ui/UIWidget.h"NS_CC_BEGINnamespace ui {typedef enum{    LAYOUT_COLOR_NONE,//空    LAYOUT_COLOR_SOLID,//单一固定颜色的    LAYOUT_COLOR_GRADIENT//有梯度变化的}LayoutBackGroundColorType;//容器背景颜色类型typedef enum{    LAYOUT_ABSOLUTE,//绝对    LAYOUT_LINEAR_VERTICAL,//线性 垂直    LAYOUT_LINEAR_HORIZONTAL,//线性 水平    LAYOUT_RELATIVE// 平面}LayoutType;//容器类型typedef enum {    LAYOUT_CLIPPING_STENCIL,//模板    LAYOUT_CLIPPING_SCISSOR//镂空}LayoutClippingType;//容器裁切类型/** *  @js NA *  @lua NA */class LayoutExecutant;    class Layout : public Widget{        DECLARE_CLASS_GUI_INFO    public:        Layout();    virtual ~Layout();    static Layout* create();            //background    /**设置背景图     * @param fileName 图片路径     * @param texType @see TextureResType.     */    void setBackGroundImage(const std::string& fileName,TextureResType texType = UI_TEX_TYPE_LOCAL);        /**如果背景图是9宫格 设置拉伸尺度     * @param capinsets of background image.     */    void setBackGroundImageCapInsets(const Rect& capInsets);        const Rect& getBackGroundImageCapInsets();        /**设置背景颜色类型*/    void setBackGroundColorType(LayoutBackGroundColorType type);        LayoutBackGroundColorType getBackGroundColorType();        /**设置背景是否使用9宫格 默认不使用*/    void setBackGroundImageScale9Enabled(bool enabled);        bool isBackGroundImageScale9Enabled();        /**设置背景颜色, 如果颜色类型是固定的*/    void setBackGroundColor(const Color3B &color);        const Color3B& getBackGroundColor();        /**设置背景颜色, 如果颜色类型是 渐变的     * @param start color     * @param end color     */    void setBackGroundColor(const Color3B &startColor, const Color3B &endColor);        const Color3B& getBackGroundStartColor();        const Color3B& getBackGroundEndColor();        /** 设置透明度.*/    void setBackGroundColorOpacity(GLubyte opacity);        GLubyte getBackGroundColorOpacity();        /** 如果背景颜色是渐变的 设置背景颜色渐变的向量     * @param vector     */    void setBackGroundColorVector(const Point &vector);        const Point& getBackGroundColorVector();        void setBackGroundImageColor(const Color3B& color);        void setBackGroundImageOpacity(GLubyte opacity);        const Color3B& getBackGroundImageColor();        GLubyte getBackGroundImageOpacity();        /**     * 移除背景img     */    void removeBackGroundImage();        /**得到背景img size*/    const Size& getBackGroundImageTextureSize() const;        /**     * 设置布局可以裁切他的内荣和孩子 默认不裁切     *如果你真的需要这个,请启用该功能。但它会降低渲染效率。     * @param clipping enabled.     */    virtual void setClippingEnabled(bool enabled);    /**设置裁切类型*/    void setClippingType(LayoutClippingType type);        LayoutClippingType getClippingType();        /**是否可以裁切*/    virtual bool isClippingEnabled();        /**     * Returns the "class name" of widget.     */    virtual std::string getDescription() const override;        /**设置容器类型*/    virtual void setLayoutType(LayoutType type);        /**得到容器类型*/    virtual LayoutType getLayoutType() const;    virtual void addChild(Node * child) override;        virtual void addChild(Node * child, int zOrder) override;        virtual void addChild(Node* child, int zOrder, int tag) override;        virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;    virtual void removeChild(Node* child, bool cleanup = true) override;           virtual void removeAllChildren() override;    /**     * Removes all children from the container,并做了清理所有正在运行的动作      */    virtual void removeAllChildrenWithCleanup(bool cleanup) override;    virtual void sortAllChildren() override;        void requestDoLayout();        virtual void onEnter() override;    virtual void onExit() override;        CC_CONSTRUCTOR_ACCESS:    //override "init" method of widget.    virtual bool init() override;    protected:    //override "onSizeChanged" method of widget.    virtual void onSizeChanged() override;        //init background image renderer.    void addBackGroundImage();        void supplyTheLayoutParameterLackToChild(Widget* child);    virtual Widget* createCloneInstance() override;    virtual void copySpecialProperties(Widget* model) override;    virtual void copyClonedWidgetChildren(Widget* model) override;    /**模板类型的裁切渲染*/    void stencilClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated);    /**镂空类型的裁切渲染*/    void scissorClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated);    /**设置裁切模板size*/    void setStencilClippingSize(const Size& size);    const Rect& getClippingRect();    virtual void doLayout();        //clipping    void onBeforeVisitStencil();    void onAfterDrawStencil();    void onAfterVisitStencil();        void onBeforeVisitScissor();    void onAfterVisitScissor();    void updateBackGroundImageColor();    void updateBackGroundImageOpacity();    void updateBackGroundImageRGBA();    LayoutExecutant* createCurrentLayoutExecutant();protected:    bool _clippingEnabled;//是否裁切        //background    bool _backGroundScale9Enabled;//是否开启9宫格    Node* _backGroundImage;//背景图    std::string _backGroundImageFileName;//背景name    Rect _backGroundImageCapInsets;//拉伸区域    LayoutBackGroundColorType _colorType;//背景颜色类型    TextureResType _bgImageTexType;//贴图类型    LayerColor* _colorRender;//正常渲染层 当前只用一个 由类型决定    LayerGradient* _gradientRender;//渐变渲染层    Color3B _cColor;//正常模式颜色值    Color3B _gStartColor;//渐变模式颜色的开始值    Color3B _gEndColor;//渐变模式颜色的结束值    Point _alongVector;//渐变颜色方向    GLubyte _cOpacity;//透明度    Size _backGroundImageTextureSize;//背景贴图size    LayoutType _layoutType;//容器类型    LayoutClippingType _clippingType;//裁切类型    DrawNode* _clippingStencil;//绘制几何裁切区域    bool _scissorRectDirty;//多余的变量    Rect _clippingRect;//裁切的区域    Layout* _clippingParent;//裁切布局    bool _doLayoutDirty;//是否开启布局    bool _clippingRectDirty;//是否计算裁切区域 默认true 由于计算裁切区域逻辑较复杂    //所以计算一次之后就不计算了 _clippingRectDirty = false;        //clipping    GLboolean _currentStencilEnabled;    GLuint _currentStencilWriteMask;    GLenum _currentStencilFunc;    GLint _currentStencilRef;    GLuint _currentStencilValueMask;    GLenum _currentStencilFail;    GLenum _currentStencilPassDepthFail;    GLenum _currentStencilPassDepthPass;    GLboolean _currentDepthWriteMask;        GLboolean _currentAlphaTestEnabled;    GLenum _currentAlphaTestFunc;    GLclampf _currentAlphaTestRef;            Color3B _backGroundImageColor;    GLubyte _backGroundImageOpacity;        LayoutExecutant* _curLayoutExecutant;//布局执行者        GLint _mask_layer_le;    GroupCommand _groupCommand;    CustomCommand _beforeVisitCmdStencil;    CustomCommand _afterDrawStencilCmd;    CustomCommand _afterVisitCmdStencil;    CustomCommand _beforeVisitCmdScissor;    CustomCommand _afterVisitCmdScissor;};    }NS_CC_END#endif /* defined(__Layout__) */
#include "ui/UILayout.h"#include "ui/UIHelper.h"#include "extensions/GUI/CCControlExtension/CCScale9Sprite.h"#include "kazmath/GL/matrix.h"#include "CCGLProgram.h"#include "CCShaderCache.h"#include "CCDirector.h"#include "CCDrawingPrimitives.h"#include "renderer/CCRenderer.h"#include "renderer/CCGroupCommand.h"#include "renderer/CCCustomCommand.h"NS_CC_BEGINnamespace ui {//布局执行者class LayoutExecutant : public Ref{public:    LayoutExecutant(){};    virtual ~LayoutExecutant(){};    static LayoutExecutant* create();    virtual void doLayout(const Size& layoutSize, Vector<Node*> container){};};//线性垂直 布局执行者class LinearVerticalLayoutExecutant : public LayoutExecutant{public:    LinearVerticalLayoutExecutant(){};    virtual ~LinearVerticalLayoutExecutant(){};    static LinearVerticalLayoutExecutant* create();    virtual void doLayout(const Size& layoutSize, Vector<Node*> container);};//线性水平 布局执行者class LinearHorizontalLayoutExecutant : public LayoutExecutant{public:    LinearHorizontalLayoutExecutant(){};    virtual ~LinearHorizontalLayoutExecutant(){};    static LinearHorizontalLayoutExecutant* create();    virtual void doLayout(const Size& layoutSize, Vector<Node*> container);};//相对 布局执行者class RelativeLayoutExecutant : public LayoutExecutant{public:    RelativeLayoutExecutant(){};    virtual ~RelativeLayoutExecutant(){};    static RelativeLayoutExecutant* create();    virtual void doLayout(const Size& layoutSize, Vector<Node*> container);};    LayoutExecutant* LayoutExecutant::create(){    LayoutExecutant* exe = new LayoutExecutant();    if (exe)    {        exe->autorelease();        return exe;    }    CC_SAFE_DELETE(exe);    return nullptr;}    LinearVerticalLayoutExecutant* LinearVerticalLayoutExecutant::create(){    LinearVerticalLayoutExecutant* exe = new LinearVerticalLayoutExecutant();    if (exe)    {        exe->autorelease();        return exe;    }    CC_SAFE_DELETE(exe);    return nullptr;}LinearHorizontalLayoutExecutant* LinearHorizontalLayoutExecutant::create(){    LinearHorizontalLayoutExecutant* exe = new LinearHorizontalLayoutExecutant();    if (exe)    {        exe->autorelease();        return exe;    }    CC_SAFE_DELETE(exe);    return nullptr;}RelativeLayoutExecutant* RelativeLayoutExecutant::create(){    RelativeLayoutExecutant* exe = new RelativeLayoutExecutant();    if (exe)    {        exe->autorelease();        return exe;    }    CC_SAFE_DELETE(exe);    return nullptr;}//线性垂直 布局执行者void LinearVerticalLayoutExecutant::doLayout(const cocos2d::Size &layoutSize, Vector<cocos2d::Node *> container){    float topBoundary = layoutSize.height;//布局高度        for (auto& subWidget : container)//遍历所有容器    {        Widget* child = dynamic_cast<Widget*>(subWidget);        if (child)//是widget类型        {            LinearLayoutParameter* layoutParameter = dynamic_cast<LinearLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR));                        if (layoutParameter)//是线性布局参数            {                LinearGravity childGravity = layoutParameter->getGravity();//重力类型                Point ap = child->getAnchorPoint();//锚点                Size cs = child->getSize();//大小                float finalPosX = ap.x * cs.width;//最终X位置                float finalPosY = topBoundary - ((1.0f-ap.y) * cs.height);//最终Y位置                switch (childGravity)                {                    case LINEAR_GRAVITY_NONE:                    case LINEAR_GRAVITY_LEFT:                        break;                    case LINEAR_GRAVITY_RIGHT:                        finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width);//最终X位置                        break;                    case LINEAR_GRAVITY_CENTER_HORIZONTAL:                        finalPosX = layoutSize.width / 2.0f - cs.width * (0.5f-ap.x);//最终Y位置                        break;                    default:                        break;                }                Margin mg = layoutParameter->getMargin();//得到间距                finalPosX += mg.left;//加上左间距 右移                finalPosY -= mg.top;//减去上间距 下移                child->setPosition(Point(finalPosX, finalPosY));                topBoundary = child->getBottomInParent() - mg.bottom;            }        }    }}//线性水平 布局执行者 类似上void LinearHorizontalLayoutExecutant::doLayout(const cocos2d::Size &layoutSize, Vector<cocos2d::Node *> container){    float leftBoundary = 0.0f;    for (auto& subWidget : container)    {        Widget* child = dynamic_cast<Widget*>(subWidget);        if (child)        {            LinearLayoutParameter* layoutParameter = dynamic_cast<LinearLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR));            if (layoutParameter)            {                LinearGravity childGravity = layoutParameter->getGravity();                Point ap = child->getAnchorPoint();                Size cs = child->getSize();                float finalPosX = leftBoundary + (ap.x * cs.width);                float finalPosY = layoutSize.height - (1.0f - ap.y) * cs.height;                switch (childGravity)                {                    case LINEAR_GRAVITY_NONE:                    case LINEAR_GRAVITY_TOP:                        break;                    case LINEAR_GRAVITY_BOTTOM:                        finalPosY = ap.y * cs.height;                        break;                    case LINEAR_GRAVITY_CENTER_VERTICAL:                        finalPosY = layoutSize.height / 2.0f - cs.height * (0.5f - ap.y);                        break;                    default:                        break;                }                Margin mg = layoutParameter->getMargin();                finalPosX += mg.left;                finalPosY -= mg.top;                child->setPosition(Point(finalPosX, finalPosY));                leftBoundary = child->getRightInParent() + mg.right;            }        }    }}//相对 布局执行者void RelativeLayoutExecutant::doLayout(const cocos2d::Size &layoutSize, Vector<cocos2d::Node *> container){    ssize_t unlayoutChildCount = 0;    Vector<Widget*> widgetChildren;    for (auto& subWidget : container)    {        Widget* child = dynamic_cast<Widget*>(subWidget);        if (child)        {            RelativeLayoutParameter* layoutParameter = dynamic_cast<RelativeLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE));            layoutParameter->_put = false;            unlayoutChildCount++;            widgetChildren.pushBack(child);        }    }    while (unlayoutChildCount > 0)    {        for (auto& subWidget : widgetChildren)        {            Widget* child = static_cast<Widget*>(subWidget);            RelativeLayoutParameter* layoutParameter = dynamic_cast<RelativeLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE));                        if (layoutParameter)            {                if (layoutParameter->_put)                {                    continue;                }                Point ap = child->getAnchorPoint();                Size cs = child->getSize();                RelativeAlign align = layoutParameter->getAlign();                const char* relativeName = layoutParameter->getRelativeToWidgetName();                Widget* relativeWidget = nullptr;                RelativeLayoutParameter* relativeWidgetLP = nullptr;                float finalPosX = 0.0f;                float finalPosY = 0.0f;                if (relativeName && strcmp(relativeName, ""))                {                    for (auto& sWidget : widgetChildren)                    {                        if (sWidget)                        {                            RelativeLayoutParameter* rlayoutParameter = dynamic_cast<RelativeLayoutParameter*>(sWidget->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE));                            if (rlayoutParameter && strcmp(rlayoutParameter->getRelativeName(), relativeName) == 0)                            {                                relativeWidget = sWidget;                                relativeWidgetLP = rlayoutParameter;                                break;                            }                        }                    }                }                switch (align)                {                    case RELATIVE_ALIGN_NONE:                    case RELATIVE_ALIGN_PARENT_TOP_LEFT:                        finalPosX = ap.x * cs.width;                        finalPosY = layoutSize.height - ((1.0f - ap.y) * cs.height);                        break;                    case RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL:                        finalPosX = layoutSize.width * 0.5f - cs.width * (0.5f - ap.x);                        finalPosY = layoutSize.height - ((1.0f - ap.y) * cs.height);                        break;                    case RELATIVE_ALIGN_PARENT_TOP_RIGHT:                        finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width);                        finalPosY = layoutSize.height - ((1.0f - ap.y) * cs.height);                        break;                    case RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL:                        finalPosX = ap.x * cs.width;                        finalPosY = layoutSize.height * 0.5f - cs.height * (0.5f - ap.y);                        break;                    case RELATIVE_CENTER_IN_PARENT:                        finalPosX = layoutSize.width * 0.5f - cs.width * (0.5f - ap.x);                        finalPosY = layoutSize.height * 0.5f - cs.height * (0.5f - ap.y);                        break;                    case RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL:                        finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width);                        finalPosY = layoutSize.height * 0.5f - cs.height * (0.5f - ap.y);                        break;                    case RELATIVE_ALIGN_PARENT_LEFT_BOTTOM:                        finalPosX = ap.x * cs.width;                        finalPosY = ap.y * cs.height;                        break;                    case RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL:                        finalPosX = layoutSize.width * 0.5f - cs.width * (0.5f - ap.x);                        finalPosY = ap.y * cs.height;                        break;                    case RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM:                        finalPosX = layoutSize.width - ((1.0f - ap.x) * cs.width);                        finalPosY = ap.y * cs.height;                        break;                                            case RELATIVE_LOCATION_ABOVE_LEFTALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationBottom = relativeWidget->getTopInParent();                            float locationLeft = relativeWidget->getLeftInParent();                            finalPosY = locationBottom + ap.y * cs.height;                            finalPosX = locationLeft + ap.x * cs.width;                        }                        break;                    case RELATIVE_LOCATION_ABOVE_CENTER:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            Size rbs = relativeWidget->getSize();                            float locationBottom = relativeWidget->getTopInParent();                                                        finalPosY = locationBottom + ap.y * cs.height;                            finalPosX = relativeWidget->getLeftInParent() + rbs.width * 0.5f + ap.x * cs.width - cs.width * 0.5f;                        }                        break;                    case RELATIVE_LOCATION_ABOVE_RIGHTALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationBottom = relativeWidget->getTopInParent();                            float locationRight = relativeWidget->getRightInParent();                            finalPosY = locationBottom + ap.y * cs.height;                            finalPosX = locationRight - (1.0f - ap.x) * cs.width;                        }                        break;                    case RELATIVE_LOCATION_LEFT_OF_TOPALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationTop = relativeWidget->getTopInParent();                            float locationRight = relativeWidget->getLeftInParent();                            finalPosY = locationTop - (1.0f - ap.y) * cs.height;                            finalPosX = locationRight - (1.0f - ap.x) * cs.width;                        }                        break;                    case RELATIVE_LOCATION_LEFT_OF_CENTER:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            Size rbs = relativeWidget->getSize();                            float locationRight = relativeWidget->getLeftInParent();                            finalPosX = locationRight - (1.0f - ap.x) * cs.width;                                                        finalPosY = relativeWidget->getBottomInParent() + rbs.height * 0.5f + ap.y * cs.height - cs.height * 0.5f;                        }                        break;                    case RELATIVE_LOCATION_LEFT_OF_BOTTOMALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationBottom = relativeWidget->getBottomInParent();                            float locationRight = relativeWidget->getLeftInParent();                            finalPosY = locationBottom + ap.y * cs.height;                            finalPosX = locationRight - (1.0f - ap.x) * cs.width;                        }                        break;                    case RELATIVE_LOCATION_RIGHT_OF_TOPALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationTop = relativeWidget->getTopInParent();                            float locationLeft = relativeWidget->getRightInParent();                            finalPosY = locationTop - (1.0f - ap.y) * cs.height;                            finalPosX = locationLeft + ap.x * cs.width;                        }                        break;                    case RELATIVE_LOCATION_RIGHT_OF_CENTER:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            Size rbs = relativeWidget->getSize();                            float locationLeft = relativeWidget->getRightInParent();                            finalPosX = locationLeft + ap.x * cs.width;                                                        finalPosY = relativeWidget->getBottomInParent() + rbs.height * 0.5f + ap.y * cs.height - cs.height * 0.5f;                        }                        break;                    case RELATIVE_LOCATION_RIGHT_OF_BOTTOMALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationBottom = relativeWidget->getBottomInParent();                            float locationLeft = relativeWidget->getRightInParent();                            finalPosY = locationBottom + ap.y * cs.height;                            finalPosX = locationLeft + ap.x * cs.width;                        }                        break;                    case RELATIVE_LOCATION_BELOW_LEFTALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationTop = relativeWidget->getBottomInParent();                            float locationLeft = relativeWidget->getLeftInParent();                            finalPosY = locationTop - (1.0f - ap.y) * cs.height;                            finalPosX = locationLeft + ap.x * cs.width;                        }                        break;                    case RELATIVE_LOCATION_BELOW_CENTER:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            Size rbs = relativeWidget->getSize();                            float locationTop = relativeWidget->getBottomInParent();                                                        finalPosY = locationTop - (1.0f - ap.y) * cs.height;                            finalPosX = relativeWidget->getLeftInParent() + rbs.width * 0.5f + ap.x * cs.width - cs.width * 0.5f;                        }                        break;                    case RELATIVE_LOCATION_BELOW_RIGHTALIGN:                        if (relativeWidget)                        {                            if (relativeWidgetLP && !relativeWidgetLP->_put)                            {                                continue;                            }                            float locationTop = relativeWidget->getBottomInParent();                            float locationRight = relativeWidget->getRightInParent();                            finalPosY = locationTop - (1.0f - ap.y) * cs.height;                            finalPosX = locationRight - (1.0f - ap.x) * cs.width;                        }                        break;                    default:                        break;                }                Margin relativeWidgetMargin;                Margin mg = layoutParameter->getMargin();                if (relativeWidgetLP)                {                    relativeWidgetMargin = relativeWidgetLP->getMargin();                }                //handle margin                switch (align)                {                    case RELATIVE_ALIGN_NONE:                    case RELATIVE_ALIGN_PARENT_TOP_LEFT:                        finalPosX += mg.left;                        finalPosY -= mg.top;                        break;                    case RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL:                        finalPosY -= mg.top;                        break;                    case RELATIVE_ALIGN_PARENT_TOP_RIGHT:                        finalPosX -= mg.right;                        finalPosY -= mg.top;                        break;                    case RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL:                        finalPosX += mg.left;                        break;                    case RELATIVE_CENTER_IN_PARENT:                        break;                    case RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL:                        finalPosX -= mg.right;                        break;                    case RELATIVE_ALIGN_PARENT_LEFT_BOTTOM:                        finalPosX += mg.left;                        finalPosY += mg.bottom;                        break;                    case RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL:                        finalPosY += mg.bottom;                        break;                    case RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM:                        finalPosX -= mg.right;                        finalPosY += mg.bottom;                        break;                                            case RELATIVE_LOCATION_ABOVE_LEFTALIGN:                        finalPosY += mg.bottom;                        finalPosX += mg.left;                        break;                    case RELATIVE_LOCATION_ABOVE_RIGHTALIGN:                        finalPosY += mg.bottom;                        finalPosX -= mg.right;                        break;                    case RELATIVE_LOCATION_ABOVE_CENTER:                        finalPosY += mg.bottom;                        break;                                            case RELATIVE_LOCATION_LEFT_OF_TOPALIGN:                        finalPosX -= mg.right;                        finalPosY -= mg.top;                        break;                    case RELATIVE_LOCATION_LEFT_OF_BOTTOMALIGN:                        finalPosX -= mg.right;                        finalPosY += mg.bottom;                        break;                    case RELATIVE_LOCATION_LEFT_OF_CENTER:                        finalPosX -= mg.right;                        break;                                            case RELATIVE_LOCATION_RIGHT_OF_TOPALIGN:                        finalPosX += mg.left;                        finalPosY -= mg.top;                        break;                    case RELATIVE_LOCATION_RIGHT_OF_BOTTOMALIGN:                        finalPosX += mg.left;                        finalPosY += mg.bottom;                        break;                    case RELATIVE_LOCATION_RIGHT_OF_CENTER:                        finalPosX += mg.left;                        break;                                            case RELATIVE_LOCATION_BELOW_LEFTALIGN:                        finalPosY -= mg.top;                        finalPosX += mg.left;                        break;                    case RELATIVE_LOCATION_BELOW_RIGHTALIGN:                        finalPosY -= mg.top;                        finalPosX -= mg.right;                        break;                    case RELATIVE_LOCATION_BELOW_CENTER:                        finalPosY -= mg.top;                        break;                    default:                        break;                }                child->setPosition(Point(finalPosX, finalPosY));                layoutParameter->_put = true;                unlayoutChildCount--;            }        }    }    widgetChildren.clear();}//渲染层Zorderstatic const int BACKGROUNDIMAGE_Z = (-1);static const int BCAKGROUNDCOLORRENDERER_Z = (-2);static GLint g_sStencilBits = -1;static GLint s_layer = -1;    IMPLEMENT_CLASS_GUI_INFO(Layout)Layout::Layout():_clippingEnabled(false),_backGroundScale9Enabled(false),_backGroundImage(nullptr),_backGroundImageFileName(""),_backGroundImageCapInsets(Rect::ZERO),_colorType(LAYOUT_COLOR_NONE),_bgImageTexType(UI_TEX_TYPE_LOCAL),_colorRender(nullptr),_gradientRender(nullptr),_cColor(Color3B::WHITE),_gStartColor(Color3B::WHITE),_gEndColor(Color3B::WHITE),_alongVector(Point(0.0f, -1.0f)),_cOpacity(255),_backGroundImageTextureSize(Size::ZERO),_layoutType(LAYOUT_ABSOLUTE),_clippingType(LAYOUT_CLIPPING_STENCIL),_clippingStencil(nullptr),_scissorRectDirty(false),_clippingRect(Rect::ZERO),_clippingParent(nullptr),_doLayoutDirty(true),_clippingRectDirty(true),_currentStencilEnabled(GL_FALSE),_currentStencilWriteMask(~0),_currentStencilFunc(GL_ALWAYS),_currentStencilRef(0),_currentStencilValueMask(~0),_currentStencilFail(GL_KEEP),_currentStencilPassDepthFail(GL_KEEP),_currentStencilPassDepthPass(GL_KEEP),_currentDepthWriteMask(GL_TRUE),_currentAlphaTestEnabled(GL_FALSE),_currentAlphaTestFunc(GL_ALWAYS),_currentAlphaTestRef(1),_backGroundImageColor(Color3B::WHITE),_backGroundImageOpacity(255),_curLayoutExecutant(nullptr){    _widgetType = WidgetTypeContainer;//默认 为容器类型}Layout::~Layout(){    CC_SAFE_RELEASE(_clippingStencil);    CC_SAFE_RELEASE(_curLayoutExecutant);}    void Layout::onEnter(){    Widget::onEnter();    if (_clippingStencil)    {        _clippingStencil->onEnter();    }    _doLayoutDirty = true;//可以布局    _clippingRectDirty = true;//可以计算裁切矩形}    void Layout::onExit(){    Widget::onExit();    if (_clippingStencil)    {        _clippingStencil->onExit();    }}Layout* Layout::create(){    Layout* layout = new Layout();    if (layout && layout->init())    {        layout->autorelease();        return layout;    }    CC_SAFE_DELETE(layout);    return nullptr;}bool Layout::init(){    if (ProtectedNode::init())    {        initRenderer();        setBright(true);        ignoreContentAdaptWithSize(false);        setSize(Size::ZERO);        setAnchorPoint(Point::ZERO);//锚点左下        return true;    }    return false;}    void Layout::addChild(Node *child){    Widget::addChild(child);}void Layout::addChild(Node * child, int zOrder){    Widget::addChild(child, zOrder);}void Layout::addChild(Node *child, int zOrder, int tag){    supplyTheLayoutParameterLackToChild(static_cast<Widget*>(child));//设置布局参数    Widget::addChild(child, zOrder, tag);//添加child    _doLayoutDirty = true;}    void Layout::removeChild(Node *child, bool cleanup){    Widget::removeChild(child, cleanup);    _doLayoutDirty = true;}    void Layout::removeAllChildren(){    Widget::removeAllChildren();}    void Layout::removeAllChildrenWithCleanup(bool cleanup){    Widget::removeAllChildrenWithCleanup(cleanup);    _doLayoutDirty = true;}bool Layout::isClippingEnabled(){    return _clippingEnabled;}void Layout::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated){    if (!_enabled)//不可用就直接return    {        return;    }    adaptRenderers();//对应各自的逻辑处理    if (_clippingEnabled)//可以裁切    {        switch (_clippingType)//裁切类型        {            case LAYOUT_CLIPPING_STENCIL://模板                stencilClippingVisit(renderer, parentTransform, parentTransformUpdated);//专属自己的visit                break;            case LAYOUT_CLIPPING_SCISSOR://镂空                scissorClippingVisit(renderer, parentTransform, parentTransformUpdated);//专属自己的visit                break;            default:                break;        }    }    else//不可以裁切 基本的visit    {        ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated);    }}    void Layout::sortAllChildren(){    Widget::sortAllChildren();//排序子节点    doLayout();//布局}//模板类型裁切void Layout::stencilClippingVisit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated){    if(!_visible)        return;        bool dirty = parentTransformUpdated || _transformUpdated;    if(dirty)        _modelViewTransform = transform(parentTransform);    _transformUpdated = false;    // IMPORTANT:    // To ease the migration to v3.0, we still support the kmGL stack,    // but it is deprecated and your code should not rely on it    kmGLPushMatrix();    kmGLLoadMatrix(&_modelViewTransform);    //Add group command    _groupCommand.init(_globalZOrder);    renderer->addCommand(&_groupCommand);        renderer->pushGroup(_groupCommand.getRenderQueueID());        _beforeVisitCmdStencil.init(_globalZOrder);    _beforeVisitCmdStencil.func = CC_CALLBACK_0(Layout::onBeforeVisitStencil, this);    renderer->addCommand(&_beforeVisitCmdStencil);        _clippingStencil->visit(renderer, _modelViewTransform, dirty);        _afterDrawStencilCmd.init(_globalZOrder);    _afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this);    renderer->addCommand(&_afterDrawStencilCmd);        int i = 0;      // used by _children    int j = 0;      // used by _protectedChildren        sortAllChildren();    sortAllProtectedChildren();        //    // draw children and protectedChildren zOrder < 0    //    for( ; i < _children.size(); i++ )    {        auto node = _children.at(i);                if ( node && node->getLocalZOrder() < 0 )            node->visit(renderer, _modelViewTransform, dirty);        else            break;    }        for( ; j < _protectedChildren.size(); j++ )    {        auto node = _protectedChildren.at(j);                if ( node && node->getLocalZOrder() < 0 )            node->visit(renderer, _modelViewTransform, dirty);        else            break;    }        //    // draw self    //    this->draw(renderer, _modelViewTransform, dirty);        //    // draw children and protectedChildren zOrder >= 0    //    for(auto it=_protectedChildren.cbegin()+j; it != _protectedChildren.cend(); ++it)        (*it)->visit(renderer, _modelViewTransform, dirty);        for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)        (*it)->visit(renderer, _modelViewTransform, dirty);        _afterVisitCmdStencil.init(_globalZOrder);    _afterVisitCmdStencil.func = CC_CALLBACK_0(Layout::onAfterVisitStencil, this);    renderer->addCommand(&_afterVisitCmdStencil);        renderer->popGroup();        kmGLPopMatrix();}    void Layout::onBeforeVisitStencil(){    s_layer++;    GLint mask_layer = 0x1 << s_layer;    GLint mask_layer_l = mask_layer - 1;    _mask_layer_le = mask_layer | mask_layer_l;    _currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);    glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&_currentStencilWriteMask);    glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&_currentStencilFunc);    glGetIntegerv(GL_STENCIL_REF, &_currentStencilRef);    glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&_currentStencilValueMask);    glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&_currentStencilFail);    glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&_currentStencilPassDepthFail);    glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);        glEnable(GL_STENCIL_TEST);    CHECK_GL_ERROR_DEBUG();    glStencilMask(mask_layer);    glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);    glDepthMask(GL_FALSE);    glStencilFunc(GL_NEVER, mask_layer, mask_layer);    glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);    kmGLMatrixMode(KM_GL_MODELVIEW);    kmGLPushMatrix();    kmGLLoadIdentity();        kmGLMatrixMode(KM_GL_PROJECTION);    kmGLPushMatrix();    kmGLLoadIdentity();        DrawPrimitives::drawSolidRect(Point(-1,-1), Point(1,1), Color4F(1, 1, 1, 1));        kmGLMatrixMode(KM_GL_PROJECTION);    kmGLPopMatrix();    kmGLMatrixMode(KM_GL_MODELVIEW);    kmGLPopMatrix();    glStencilFunc(GL_NEVER, mask_layer, mask_layer);    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);}void Layout::onAfterDrawStencil(){    glDepthMask(_currentDepthWriteMask);    glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);}void Layout::onAfterVisitStencil(){    glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);    glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);    glStencilMask(_currentStencilWriteMask);    if (!_currentStencilEnabled)    {        glDisable(GL_STENCIL_TEST);    }    s_layer--;}    void Layout::onBeforeVisitScissor(){    Rect clippingRect = getClippingRect();    glEnable(GL_SCISSOR_TEST);//裁切开始    auto glview = Director::getInstance()->getOpenGLView();//得到OpenGL 窗口    glview->setScissorInPoints(clippingRect.origin.x, clippingRect.origin.y, clippingRect.size.width, clippingRect.size.height);//根据裁切范围进行裁切}void Layout::onAfterVisitScissor(){    glDisable(GL_SCISSOR_TEST);//裁切终止}    void Layout::scissorClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated){//模板裁切渲染    _beforeVisitCmdScissor.init(_globalZOrder);    _beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this);    renderer->addCommand(&_beforeVisitCmdScissor);    ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated);        _afterVisitCmdScissor.init(_globalZOrder);    _afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this);    renderer->addCommand(&_afterVisitCmdScissor);}void Layout::setClippingEnabled(bool able){    if (able == _clippingEnabled)//默认不能裁切 若和当前值相同 说明设置过 不必再详加判断 防止外部调用多次出现 不必要的重复逻辑    {        return;    }    _clippingEnabled = able;//是否可以裁切    switch (_clippingType)    {        case LAYOUT_CLIPPING_STENCIL://裁切类型为 模板            if (able)//若能裁切            {                static bool once = true;                if (once)                {                    glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits);//裁切                    if (g_sStencilBits <= 0)                    {                        CCLOG("Stencil buffer is not enabled.");                    }                    once = false;                }                _clippingStencil = DrawNode::create();//创建 绘制对象                if (_running)//若该节点在运行                {                    _clippingStencil->onEnter();//初始化绘制对象                }                _clippingStencil->retain();//绘制对象引用次数++                setStencilClippingSize(_size);//设置裁切区域            }            else//若不能裁切            {                if (_running)//若该节点在运行                {                    _clippingStencil->onExit();//绘制对象 退出                }                _clippingStencil->release();//计数--                _clippingStencil = nullptr;//置空            }            break;        default:            break;    }}    void Layout::setClippingType(LayoutClippingType type){    if (type == _clippingType)    {        return;    }    bool clippingEnabled = isClippingEnabled();    setClippingEnabled(false);    _clippingType = type;//设置裁切类型    setClippingEnabled(clippingEnabled);}    LayoutClippingType Layout::getClippingType(){    return _clippingType;}    void Layout::setStencilClippingSize(const Size &size){    if (_clippingEnabled && _clippingType == LAYOUT_CLIPPING_STENCIL)    {//若可以裁切 裁切类型为 模板        Point rect[4];//设置裁切范围        rect[0] = Point::ZERO;        rect[1] = Point(_size.width, 0);        rect[2] = Point(_size.width, _size.height);        rect[3] = Point(0, _size.height);        Color4F green(0, 1, 0, 1);        _clippingStencil->clear();        _clippingStencil->drawPolygon(rect, 4, green, 0, green);//花多边形    }}//得到裁切的矩形const Rect& Layout::getClippingRect(){    if (_clippingRectDirty)    {        Point worldPos = convertToWorldSpace(Point::ZERO);//世界坐标        AffineTransform t = getNodeToWorldAffineTransform();//仿射旋转        float scissorWidth = _size.width*t.a;//裁切宽度        float scissorHeight = _size.height*t.d;//裁切高度        Rect parentClippingRect;//父节点裁切矩形        Layout* parent = this;//从自己开始        while (parent)        {            parent = dynamic_cast<Layout*>(parent->getParent());            if(parent)//存在layout的父节点            {                if (parent->isClippingEnabled())//若该节点可以裁切                {                    _clippingParent = parent;//保存裁切节点                    break;                }            }        }                if (_clippingParent)//如果找到裁切父节点        {            parentClippingRect = _clippingParent->getClippingRect();//得到裁切矩形范围            float finalX = worldPos.x - (scissorWidth * _anchorPoint.x);            float finalY = worldPos.y - (scissorHeight * _anchorPoint.y);            float finalWidth = scissorWidth;            float finalHeight = scissorHeight;//计算得出裁切范围                        float leftOffset = worldPos.x - parentClippingRect.origin.x;            if (leftOffset < 0.0f)            {                finalX = parentClippingRect.origin.x;                finalWidth += leftOffset;            }            float rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.origin.x + parentClippingRect.size.width);            if (rightOffset > 0.0f)            {                finalWidth -= rightOffset;            }            float topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.origin.y + parentClippingRect.size.height);            if (topOffset > 0.0f)            {                finalHeight -= topOffset;            }            float bottomOffset = worldPos.y - parentClippingRect.origin.y;            if (bottomOffset < 0.0f)            {                finalY = parentClippingRect.origin.x;                finalHeight += bottomOffset;            }            if (finalWidth < 0.0f)            {                finalWidth = 0.0f;            }            if (finalHeight < 0.0f)            {                finalHeight = 0.0f;            }            _clippingRect.origin.x = finalX;            _clippingRect.origin.y = finalY;            _clippingRect.size.width = finalWidth;            _clippingRect.size.height = finalHeight;        }        else        {            _clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x);            _clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y);            _clippingRect.size.width = scissorWidth;            _clippingRect.size.height = scissorHeight;        }        _clippingRectDirty = false;//置为不可裁切    }    return _clippingRect;}void Layout::onSizeChanged(){    Widget::onSizeChanged();    setStencilClippingSize(_size);//设置裁切范围    _doLayoutDirty = true;//开启布局    _clippingRectDirty = true;//允许计算裁切区域    if (_backGroundImage)//若背景存在    {//设置背景位置居中        _backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f));        if (_backGroundScale9Enabled && _backGroundImage)        {//若使用九宫格 设置透明度            static_cast<extension::Scale9Sprite*>(_backGroundImage)->setPreferredSize(_size);        }    }    //设置渲染器的渲染区域大小    if (_colorRender)    {        _colorRender->setContentSize(_size);    }    if (_gradientRender)    {        _gradientRender->setContentSize(_size);    }}void Layout::setBackGroundImageScale9Enabled(bool able){    if (_backGroundScale9Enabled == able)    {        return;    }    removeProtectedChild(_backGroundImage);    _backGroundImage = nullptr;//置空背景    _backGroundScale9Enabled = able;    addBackGroundImage();//添加背景 设置背景属性    setBackGroundImage(_backGroundImageFileName,_bgImageTexType);    setBackGroundImageCapInsets(_backGroundImageCapInsets);}    bool Layout::isBackGroundImageScale9Enabled(){    return _backGroundScale9Enabled;}void Layout::setBackGroundImage(const std::string& fileName,TextureResType texType){    if (fileName.empty())    {        return;    }    if (_backGroundImage == nullptr)    {        addBackGroundImage();    }    _backGroundImageFileName = fileName;    _bgImageTexType = texType;    if (_backGroundScale9Enabled)    {//若使用九宫格 加载资源        extension::Scale9Sprite* bgiScale9 = static_cast<extension::Scale9Sprite*>(_backGroundImage);        switch (_bgImageTexType)        {            case UI_TEX_TYPE_LOCAL:                bgiScale9->initWithFile(fileName);                break;            case UI_TEX_TYPE_PLIST:                bgiScale9->initWithSpriteFrameName(fileName);                break;            default:                break;        }        bgiScale9->setPreferredSize(_size);    }    else    {//若没有使用九宫格 加载资源        switch (_bgImageTexType)        {            case UI_TEX_TYPE_LOCAL:                static_cast<Sprite*>(_backGroundImage)->setTexture(fileName);                break;            case UI_TEX_TYPE_PLIST:                static_cast<Sprite*>(_backGroundImage)->setSpriteFrame(fileName);                break;            default:                break;        }    }    //保存贴图size    _backGroundImageTextureSize = _backGroundImage->getContentSize();    //设置贴图位置居中    _backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f));    updateBackGroundImageRGBA();//更新贴图颜色}void Layout::setBackGroundImageCapInsets(const Rect &capInsets){    _backGroundImageCapInsets = capInsets;    if (_backGroundScale9Enabled && _backGroundImage)    {//若使用九宫格 设置区域        static_cast<extension::Scale9Sprite*>(_backGroundImage)->setCapInsets(capInsets);    }}    const Rect& Layout::getBackGroundImageCapInsets(){    return _backGroundImageCapInsets;}void Layout::supplyTheLayoutParameterLackToChild(Widget *child){    if (!child)    {        return;    }    switch (_layoutType)    {        case LAYOUT_ABSOLUTE://绝对位置            break;        case LAYOUT_LINEAR_HORIZONTAL:        case LAYOUT_LINEAR_VERTICAL://线性        {            LinearLayoutParameter* layoutParameter = dynamic_cast<LinearLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_LINEAR));            if (!layoutParameter)            {                child->setLayoutParameter(LinearLayoutParameter::create());//设置线性布局参数            }            break;        }        case LAYOUT_RELATIVE://平面        {            RelativeLayoutParameter* layoutParameter = dynamic_cast<RelativeLayoutParameter*>(child->getLayoutParameter(LAYOUT_PARAMETER_RELATIVE));            if (!layoutParameter)            {                child->setLayoutParameter(RelativeLayoutParameter::create());//设置平面 布局参数            }            break;        }        default:            break;    }}void Layout::addBackGroundImage(){//背景图添加到节点树上    if (_backGroundScale9Enabled)    {        _backGroundImage = extension::Scale9Sprite::create();        addProtectedChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1);        static_cast<extension::Scale9Sprite*>(_backGroundImage)->setPreferredSize(_size);    }    else    {        _backGroundImage = Sprite::create();        addProtectedChild(_backGroundImage, BACKGROUNDIMAGE_Z, -1);    }    //位置居中    _backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f));}void Layout::removeBackGroundImage(){    if (!_backGroundImage)    {        return;    }//移除背景图 置空背景图及相关属性    removeProtectedChild(_backGroundImage);    _backGroundImage = nullptr;    _backGroundImageFileName = "";    _backGroundImageTextureSize = Size::ZERO;}void Layout::setBackGroundColorType(LayoutBackGroundColorType type){    if (_colorType == type)    {        return;    }    switch (_colorType)//移除渲染层    {        case LAYOUT_COLOR_NONE:            if (_colorRender)            {                removeProtectedChild(_colorRender);                _colorRender = nullptr;            }            if (_gradientRender)            {                removeProtectedChild(_gradientRender);                _gradientRender = nullptr;            }            break;        case LAYOUT_COLOR_SOLID:            if (_colorRender)            {                removeProtectedChild(_colorRender);                _colorRender = nullptr;            }            break;        case LAYOUT_COLOR_GRADIENT:            if (_gradientRender)            {                removeProtectedChild(_gradientRender);                _gradientRender = nullptr;            }            break;        default:            break;    }    _colorType = type;//重置渲染层    switch (_colorType)    {        case LAYOUT_COLOR_NONE:            break;        case LAYOUT_COLOR_SOLID:            _colorRender = LayerColor::create();            _colorRender->setContentSize(_size);            _colorRender->setOpacity(_cOpacity);            _colorRender->setColor(_cColor);            addProtectedChild(_colorRender, BCAKGROUNDCOLORRENDERER_Z, -1);            break;        case LAYOUT_COLOR_GRADIENT:            _gradientRender = LayerGradient::create();            _gradientRender->setContentSize(_size);            _gradientRender->setOpacity(_cOpacity);            _gradientRender->setStartColor(_gStartColor);            _gradientRender->setEndColor(_gEndColor);            _gradientRender->setVector(_alongVector);            addProtectedChild(_gradientRender, BCAKGROUNDCOLORRENDERER_Z, -1);            break;        default:            break;    }}    LayoutBackGroundColorType Layout::getBackGroundColorType(){    return _colorType;}void Layout::setBackGroundColor(const Color3B &color){    _cColor = color;    if (_colorRender)    {        _colorRender->setColor(color);    }}    const Color3B& Layout::getBackGroundColor(){    return _cColor;}void Layout::setBackGroundColor(const Color3B &startColor, const Color3B &endColor){    _gStartColor = startColor;    if (_gradientRender)    {        _gradientRender->setStartColor(startColor);//开始颜色    }    _gEndColor = endColor;    if (_gradientRender)    {        _gradientRender->setEndColor(endColor);//结束颜色    }}    const Color3B& Layout::getBackGroundStartColor(){    return _gStartColor;}const Color3B& Layout::getBackGroundEndColor(){    return _gEndColor;}void Layout::setBackGroundColorOpacity(GLubyte opacity){    _cOpacity = opacity;    switch (_colorType)    {        case LAYOUT_COLOR_NONE:            break;        case LAYOUT_COLOR_SOLID://单一的颜色透明度            _colorRender->setOpacity(opacity);            break;        case LAYOUT_COLOR_GRADIENT:            _gradientRender->setOpacity(opacity);//渐变的颜色透明度            break;        default:            break;    }}    GLubyte Layout::getBackGroundColorOpacity(){    return _cOpacity;}void Layout::setBackGroundColorVector(const Point &vector){    _alongVector = vector;    if (_gradientRender)    {        _gradientRender->setVector(vector);//设置渐变方向    }}    const Point& Layout::getBackGroundColorVector(){    return _alongVector;}void Layout::setBackGroundImageColor(const Color3B &color){    _backGroundImageColor = color;    updateBackGroundImageColor();}void Layout::setBackGroundImageOpacity(GLubyte opacity){    _backGroundImageOpacity = opacity;    updateBackGroundImageOpacity();}const Color3B& Layout::getBackGroundImageColor(){    return _backGroundImageColor;}GLubyte Layout::getBackGroundImageOpacity(){    return _backGroundImageOpacity;}void Layout::updateBackGroundImageColor(){    if (_backGroundImage)    {        _backGroundImage->setColor(_backGroundImageColor);    }}void Layout::updateBackGroundImageOpacity(){    if (_backGroundImage)    {        _backGroundImage->setOpacity(_backGroundImageOpacity);    }}void Layout::updateBackGroundImageRGBA(){    if (_backGroundImage)    {//设置背景color opacity        _backGroundImage->setColor(_backGroundImageColor);        _backGroundImage->setOpacity(_backGroundImageOpacity);    }}const Size& Layout::getBackGroundImageTextureSize() const{    return _backGroundImageTextureSize;//背景资源size}void Layout::setLayoutType(LayoutType type){    _layoutType = type;//设置布局类型    CC_SAFE_RELEASE_NULL(_curLayoutExecutant);//释放布局执行者    _curLayoutExecutant = createCurrentLayoutExecutant();//新建当前布局执行者    CC_SAFE_RETAIN(_curLayoutExecutant);//引用次数++    for (auto& child : _children)//遍历所有孩子    {        Widget* widgetChild = dynamic_cast<Widget*>(child);        if (widgetChild)        {            //提供布局参数            supplyTheLayoutParameterLackToChild(static_cast<Widget*>(child));        }    }    _doLayoutDirty = true;//开启布局}    LayoutExecutant* Layout::createCurrentLayoutExecutant(){    LayoutExecutant* exe = nullptr;    switch (_layoutType)    {        case LAYOUT_LINEAR_VERTICAL://线性垂直            exe = LinearVerticalLayoutExecutant::create();            break;        case LAYOUT_LINEAR_HORIZONTAL://线性水平            exe = LinearHorizontalLayoutExecutant::create();            break;        case LAYOUT_RELATIVE://平面            exe = RelativeLayoutExecutant::create();            break;        default:            break;    }    return exe;}LayoutType Layout::getLayoutType() const{    return _layoutType;//返回布局类型}    //请求布局void Layout::requestDoLayout(){    _doLayoutDirty = true;//开启布局}void Layout::doLayout(){    if (!_doLayoutDirty)//没开启布局 直接return    {        return;    }    if (_curLayoutExecutant)//开启布局 有了布局数据    {        //布局吧        _curLayoutExecutant->doLayout(getSize(), getChildren());    }    _doLayoutDirty = false;//布局完成}std::string Layout::getDescription() const{    return "Layout";}Widget* Layout::createCloneInstance(){    return Layout::create();}void Layout::copyClonedWidgetChildren(Widget* model){    Widget::copyClonedWidgetChildren(model);}//克隆属性void Layout::copySpecialProperties(Widget *widget){    Layout* layout = dynamic_cast<Layout*>(widget);    if (layout)    {        setBackGroundImageScale9Enabled(layout->_backGroundScale9Enabled);        setBackGroundImage(layout->_backGroundImageFileName,layout->_bgImageTexType);        setBackGroundImageCapInsets(layout->_backGroundImageCapInsets);        setBackGroundColorType(layout->_colorType);        setBackGroundColor(layout->_cColor);        setBackGroundColor(layout->_gStartColor, layout->_gEndColor);        setBackGroundColorOpacity(layout->_cOpacity);        setBackGroundColorVector(layout->_alongVector);        setLayoutType(layout->_layoutType);        setClippingEnabled(layout->_clippingEnabled);        setClippingType(layout->_clippingType);    }}}NS_CC_END


0 0